我应该如何测试从 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 对我上次检查的口味来说有点太吓人了。

编辑:我目前也仅限于 C

请先 登录 后评论

4 个回答

Dale Ragan

为了减少繁琐,您需要封装/重构 DataReader 和您在列表中保存的对象之间的映射。封装该逻辑的步骤很少。如果那是您想走的路,我可以为您发布代码。我只是不确定在 StackOverflow 上发布代码有多实用,但我可以试一试以保持简洁和重点。否则,您将被困在为读者重复索引访问器的每个期望的繁琐任务中。封装过程还将摆脱字符串,使这些字符串在您的测试中更易于重用。

此外,我目前不确定您希望使现有代码更具可测试性的程度。因为这是在构建时未考虑测试的遗留代码。

请先 登录 后评论
Rytmis

@Toran:我正在测试的是从数据库返回的数据到引用-取消引用域模型的编程映射。因此我想模拟出数据库连接。对于另一种测试,我会进行全面的集成测试。

@Dale:我猜你在这方面做得很好,我担心可能是这样。如果您有任何文章或类似内容的指针,其中有人完成了肮脏的工作并将其分解为更容易消化的步骤,我将不胜感激。代码示例也不会受到伤害。我确实知道如何解决这个问题,但在我真正敢于这样做之前,我需要完成其他事情,如果测试需要进行乏味的模拟,那么这就是我要做的。< /p>

请先 登录 后评论
Rytmis

科科斯,

那里有几件事不对劲。首先,这样做意味着我必须首先构造 Foo,然后将它们的值提供给模拟阅读器,这对 减少我正在编写的代码量没有任何作用。其次,如果值通过读取器,则 Foos 将不是 same Foos(引用相等)。它们可能相等,但即使这样也假设了太多我现在不敢触及的 Foo 类。

请先 登录 后评论
kokos

您可以将 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
请先 登录 后评论