我正在努力提高我的TDD / OO技能,每当我尝试使用TDD来影响设计时,我都会遇到一个从哪里开始的墙。
这是我的用例/故事:
确定要审核的客户的子集。为他们开始审核并发出几封信。
现在我的肌肉记忆已经打开了一个查询窗口,编写了查询,设计了一个UI,然后我必须编写一些代码来将这些位粘合在一起。
我希望域代码成为焦点,我希望它能够在测试中使用。
那么在这种情况下最简单的做法是什么?
我想我想要我的客户名单。我已经有了一个客户端对象(CSLA风格),虽然它有很多依赖,很难打破。我想我可以有一个ClientReviewClients对象并测试我获得了正确数量的评论。我需要考虑许多因素,因此看起来并不简单。无论如何,我如何嘲笑我在20个客户中有10条评论的事实?
有人可以帮助我吗?
答案 0 :(得分:4)
在这里 - 我将通过几个测试开始你:
class IdentifyClientsDueForReview {
public void CanStartSearch() {
var s = new ClientSearcher();
}
public void CanSearchClients() {
var s = new ClientSearcher();
var r = s.Find(c => c.Id == 1);
Assert.IsNotNull(r);
}
public void Finds10Clients() {
var db = new MockDB();
// Clients that need review
for (int i = 0; i < 10; i++) {
db.Add(new Client() {
NextReview = DateTime.Today.SubtractDays(i)
});
}
// Clients that don't need review
for (int i = 0; i < 10; i++) {
db.Add(new Client() {
NextReview = DateTime.Today.AddDays(i)
});
}
var s = new ClientSearcher(db);
var r = s.Find(c => c.NextReview <= DateTime.Today);
Assert.AreEqual(10, r.Count);
}
}
这是用Linq To Sql或类似的后端ORM构建的 - 否则,您可能会放弃Find
方法并使用一些硬编码的FindBy<Criteria>
方法。
这应该为您提供ClientSearcher
类,它使用一个接口来命中数据库。 MockDB
和RealDB
类都将实现该接口。
答案 1 :(得分:1)
单元测试必须快速。如果测试涉及数据库,那么它是一个集成测试(也很有价值),而不是单元测试。
至于需要审核的客户数量,我不会特别感兴趣的是我知道我有20个需要审核,但对于特定客户,我是否正确地决定该客户是否需要审核根据我的业务规则?
你可能会发现两部分系列“TDD /使用CSLA.Net的Mock对象”很有帮助:
您提到了困难的依赖关系,我强烈建议Michael Feathers 有效地使用遗留代码。这本书充满了conservative dependency-breaking techniques,可用于测试代码。
答案 2 :(得分:1)
我不熟悉C#,所以我无法帮助你解决模拟问题,我想这取决于你的测试框架。
我确实做了很多TDD,一般来说我的方法是自上而下的方法。我首先想到的是我想写的代码来做某事。让我们在你的例子中说我有一个类Client,并希望能够做一些事情:Client.initiate_reviews
所以我写了一个设置上下文的测试(一些客户,一些有评论)。然后调用Client.initiate_reviews,然后写出所有断言以确定它是否已完成其工作,即对于应该进行审核的客户端子集,现在是否正在进行审核并且所有预期都已发送?
根据方法有多少副作用,在多次测试中将其拆分可能是明智的。
然后我进入客户端类并定义方法并考虑我想要在其中编写的代码。也许是这样的:
clients = Client.find_all_due_for_review
for_each client in clients {
review = Review.start_new_for(client)
Letter.send_for_review(review)
}
然后我会编写我必须实现的方法中调用的方法的测试。 find_all_due_for_review没有副作用,但返回一些内容,当然你会在这里测试返回值,也许是否有任何改变。 并重复直到第一次测试成功。
这样每个方面都经过了适当的测试,你甚至可以使用一些可以重复使用的方法。
希望这有帮助!