通常情况下,一个班级没有直接输出;它操纵它的依赖关系,让它们做事。
例如:
internal interface IEmailer
{
void SendEmail();
}
class ReportSender
{
public IEmailer Emailer { get; set; }
public ReportSender(IEmailer emailerToUse)
{
Emailer = emailerToUse;
}
public void SendReport()
{
// Do whatever is needed to create the report
Emailer.SendEmail();
}
}
创建IEmailer的模拟并使其期望IEmailer.SendEmail()似乎暴露了太多的类内部并使测试变得脆弱。 但我想不出任何其他方法来测试这个课程。
我们应该如何为这样的类编写单元测试?
答案 0 :(得分:3)
模仿IEmailer本身并不会暴露太多的类。相反,它使开放以实现可扩展性。
某种趋势严重依赖于基于交互的测试(即模拟)使测试更加脆弱,但这更像是设计问题,而不是模拟问题。
好莱坞原则在这里可能非常有用,因为如果您的依赖项主要是围绕void
方法设计的,那么像Moq或Rhino Mocks这样的动态模拟通常会忽略方法调用,除非你特别告诉他们要关心某一个人。
答案 1 :(得分:2)
使用Mock对象是为此方法编写单元测试的正确方法。您不希望测试实际发送电子邮件。 Mock对象允许您为了单元测试而破坏不同类之间的依赖关系。
以下是使用Rhino Mocks的示例。
http://www.ayende.com/projects/rhino-mocks.aspx
IEmailer emailer = MockRepository.GenerateMock<IEmailer>();
emailer.Expect(x => x.SendEmail());
ReportSender reportSender = new ReportSender();
reportSender.Emailer = emailer;
reportSender.SendReport();
emailer.VerifyAllExpectations();
答案 2 :(得分:1)
创建IEmailer的模拟并使其期望IEmailer.SendEmail()
正是你测试它的方式。
因为这些是UNIT测试,所以你不会暴露太多。你应该行使要测试的单元的所有功能,如果你对单元有内部知识,那就没关系。
答案 3 :(得分:0)
我对单元测试还不是很有经验,所以这可能不太有用......但在我看来,你嘲笑依赖的建议是在正确的轨道上。然后,您可以在操作完成后探测模拟依赖项的状态,以确定IEmailer是否对它们执行了预期的操作?
答案 4 :(得分:0)
创建模拟IEmailer并期望调用SendEmail是测试此方案的正确方法。
答案 5 :(得分:0)
创建IEmailer的模拟并使其期望IEmailer.SendEmail()似乎暴露了太多的类内部并使测试变得脆弱。
那你为什么要公开一个需要内部接口的公共财产呢?
使界面公开,并将您的实施内部化。