没有输出的单元测试类

时间:2010-07-20 14:47:54

标签: c# unit-testing

通常情况下,一个班级没有直接输出;它操纵它的依赖关系,让它们做事。

例如:

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()似乎暴露了太多的类内部并使测试变得脆弱。 但我想不出任何其他方法来测试这个课程。

我们应该如何为这样的类编写单元测试?

6 个答案:

答案 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()似乎暴露了太多的类内部并使测试变得脆弱。

那你为什么要公开一个需要内部接口的公共财产呢?

使界面公开,并将您的实施内部化。