我应该如何测试从DataReader填充列表的方法?
因此,我正在处理一些繁重的旧代码,这些代码繁重于手动数据库操作。我试图在这里保持一些相似的外观,所以我会尽可能地使用TDD。
我正在处理的代码需要填充,比方说DataReader的List <Foo>
,它返回正常运行的Foo所需的所有字段。但是,如果我想验证代码是否实际上每数据库行返回一个列表项,我正在编写看起来像这样的测试代码:
Expect.Call(reader.Read()).Return(true); Expect.Call(reader["foo_id"]).Return((long) 1); // .... Expect.Call(reader.Read()).Return(true); Expect.Call(reader["foo_id"]).Return((long) 2); // .... Expect.Call(reader.Read()).Return(false);
这也很繁琐,也很容易破解。
我应该如何解决这个问题,以免结果变得一团乱麻呢?
顺便说一句,我目前正在使用Rhino.Mocks,但是如果结果令人信服,我可以更改它。只要替代方法不是TypeMock,就因为我最后一次检查了他们的EULA对我的口味来说太可怕了。
编辑:我目前也仅限于C2.
解决方案
回答
我们可以将Foo实例放在列表中,并将对象与读取的内容进行比较:
var arrFoos = new Foos[]{...}; // what you expect var expectedFoos = new List<Foo>(arrFoos); // make a list from the hardcoded array of expected Foos var readerResult = ReadEntireList(reader); // read everything from reader and put in List<Foo> Expect.ContainSameFoos(expectedFoos, readerResult); // compare the two lists
回答
科科斯
那里有几处错误。首先,这样做意味着我必须先构造Foos,然后将它们的值提供给模拟读取器,而模拟读取器不会减少我正在编写的代码量。其次,如果值通过阅读器传递,则Foos不会是相同的Foos(引用相等)。它们可能是相等的,但是即使如此,我仍然假设Foo类太多了,我现在不敢碰。
回答
为了减少繁琐的工作,我们将需要封装/重构DataReader与列表中保存的对象之间的映射。有很多步骤可以封装该逻辑。如果这是我们要走的路,我可以为我们发布代码。我只是不确定将代码发布到StackOverflow上有多实用,但是我可以试一下以使其简洁明了。否则,我们将陷入繁琐的任务,即重复读取器的索引访问器上的每个期望。封装过程还将摆脱字符串,并使这些字符串在测试中更可重用。
另外,我目前还不确定要使现有代码更具可测试性。由于这是遗留代码,因此并不是在考虑测试的情况下构建的。
回答
只是为了澄清一下,我们希望能够测试对SQL Server的调用返回的一些数据,或者如果我们有一些数据,则可以将其映射回模型中?
如果我们想测试对SQL的调用,返回了一些数据检出,我的答案在这里找到
回答
@Toran:我正在测试的是从数据库返回的数据到引用-取消引用域模型的程序化映射。因此,我想模拟数据库连接。对于另一种测试,我将进行全面的集成测试。
@戴尔:我想你在那儿钉得很好,我担心情况可能会如此。如果我们有指向任何文章或者诸如此类的内容的指针,例如某人做了肮脏的工作并将其分解为更容易消化的步骤,我将不胜感激。代码示例也不会受到伤害。我确实知道如何解决该问题,但是在我真正敢于做到这一点之前,我将需要完成其他工作,并且如果测试需要繁琐的模拟,那我将要做。
回答
我曾考虑过发布一些代码,然后想起了JP Boodhoo的Nothin But .NET课程。他有一个共享的示例项目,该项目是在他的一个课程中创建的。该项目托管在Google Code上,它是一个很好的资源。我相信它有一些不错的技巧供我们使用,并为我们提供有关如何重构映射的想法。整个项目是使用TDD构建的。