这是我第一次尝试进行单元测试,所以请耐心等待我.
I’m still trying to unit test a library that converts lists of POCOs to ADO.Recordsets.
I’m still trying to unit test a library that converts lists of POCOs to ADO.Recordsets.
现在,我试图编写一个创建List< Poco>,将其转换成Recordset(使用我想要测试的方法)的测试,然后检查它们是否包含相同的信息(例如,如果Poco.Foo = = RS.Foo,等等…).
这是POCO:
public class TestPoco { public string StringValue { get; set; } public int Int32Value { get; set; } public bool BoolValue { get; set; } }
…这是迄今为止的测试(我正在使用xUnit.net):
[Fact] public void TheTest() { var input = new List<TestPoco>(); input.Add(new TestPoco { BoolValue = true,Int32Value = 1,StringValue = "foo" }); var actual = input.ToRecordset(); Assert.Equal(actual.BoolValue,true); Assert.Equal(actual.Int32Value,1); Assert.Equal(actual.StringValue,"foo"); }
我不喜欢的是最后的三个声明,POCO的每个属性.
我读了很多次,一次测试中多次断言是邪恶的(我明白为什么,我同意的原因).
问题是如何摆脱他们?
我有Roy Osherove的优秀的书“The Art of Unit Testing”在我面前,他有一个例子,涵盖了这一点(对于那些有这本书的人:第7.2.6节,第202/203页):
在他的示例中,被测方法返回一个具有多个属性的AnalyzedOutput对象,他想要声明所有属性,以检查每个属性是否包含预期值.
在这种情况下的解决方案:
创建另一个AnalyzedOutput实例,用预期值填充它,如果它等于被测方法返回的值(并覆盖Equals()以便能够这样做).
但是我认为我不能这样做,因为我想要测试的方法返回一个ADODB.Recordset.
为了创建另一个具有预期值的Recordset,我首先需要从头完成创建:
// this probably doesn't actually compile,the actual conversion method // doesn't exist yet and this is just to show the idea var expected = new ADODB.RecordsetClass(); expected.Fields.Append("BoolValue",ADODB.DataTypeEnum.adBoolean); expected.Fields.Append("Int32Value",ADODB.DataTypeEnum.adInteger); expected.Fields.Append("StringValue",ADODB.DataTypeEnum.adVarWChar); expected.AddNew(); expected.BoolValue = true; expected.Int32Value = 1; expected.StringValue = "foo"; expected.Update();
我也不喜欢这个,因为这实际上是在实际的转换方法(被测方法)中的一些代码的重复,这是测试中另一回事.
那么我该怎么办?
在这种特殊情况下,这种复制水平是否仍然可以接受,还是有更好的方法来测试呢?
解决方法
我认为,在这件事的精神上,这是很好的.多重断言是“邪恶”的原因,如果我记得正确的是,它意味着你在一次测试中测试多个东西.在这种情况下,您确实在做,因为您正在测试每个字段,大概是为了确保这适用于几种不同的类型.既然这样,所有的对象平等测试都会做,反正我觉得你很清楚.
如果你真的想要武装,那么每个属性写一个测试(j / k!)