这将如何有用

时间:2011-08-26 14:55:42

标签: unit-testing tdd rhino-mocks

我还在学习Rhino Mocks的方式,时间和时间。我刚看完本教程:http://dimecasts.net/Content/WatchEpisode/12,我甚至使用记录/回放中的3.5 + AAA语法输入它,但我的问题是这对你有什么用呢?我从根本上错过了什么。

public class EmailerService
{
    public bool SendEmail(string email, string message)
    {
        return false;
    }
}

public class Emailer
{
    private IEmailerService _emailerService;
    public Emailer(IEmailerService emailerService)
    {
        this._emailerService = emailerService;
    }

    public void SendBatchEmails()
    {
        var emails = new Dictionary<string, string>
                        {
                            {"fred1@foo.com", "Hello1"},
                            {"fred2@foo.com", "Hello2"},
                            {"fred3@foo.com", "Hello3"},
                            {"fred4@foo.com", "Hello4"}
                        };
        foreach(KeyValuePair<string, string> email in emails)
        {
            if(!_emailerService.SendEmail(email.Key, email.Value))
            {
                throw new Exception(" You've Err'd");
            }
        }
    }
}

我的测试如下:

        [TestMethod]
    public void EmailerServiceTest()
    {
        //Arrange
        var emailerServie = MockRepository.GenerateMock<IEmailerService>();
        emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Return(true).Repeat.Any();

        //Act
        var emailer = new Emailer(emailerServie);
        emailer.SendBatchEmails();
    }


    [TestMethod]
    public void EmailerServiceTestException()
    {
        //Arrange
        var emailerServie = MockRepository.GenerateMock<IEmailerService>();
        emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Throw(new Exception("You've Err'd"));

        //Act
        var emailer = new Emailer(emailerServie);
        emailer.SendBatchEmails();
    }

如果您知道何时何地会失败,那么在您已经知道答案的情况下编写测试的重点是什么?感谢

2 个答案:

答案 0 :(得分:3)

出了点问题。

我想你要测试

  • 当调用emailer.SendBatchEmails时..它委托给emailerService.SendEmail。
  • 当调用emailer.SendBatchEmails并且emailerService返回失败(通过返回false)时,应该抛出异常。

在第一个测试中,您应该验证emailerService.SendEmail实际上已被调用(缺少) 对于第二个,模拟应该设置为返回false。应该设置测试方法以期望具有特定错误消息的异常。

答案 1 :(得分:2)

到目前为止,您的测试看起来像是在正确的道路上。如果您的测试看起来很明显,这是一件好事。他们在那里确保预期的行为。如果从现在开始几个月你忘记了Emailer但是你改变EmailerService以在失败时抛出异常,而不是返回false,你的测试会提醒你Emailer期待不同的行为和需要更新。

在编写单元测试时,我总是在任何实现之前做两件事:1)编写一个清晰的测试函数名称,并将方法划分为三个组件 Arrange,Act,Assert 。这有助于我清楚地保持对测试的期望,并确保我不会忘记任何事情。

看起来好像忘记了包含测试的 Assert 部分:

[TestMethod]
public void Emailer_IsCalled_SendEmailIsCalled()
{
    //Arrange
    var emailerService = MockRepository.GenerateMock<IEmailerService>();
    emailerServie.Expect(x => x.SendEmail("", "")).IgnoreArguments().Return(true).Repeat.Any();

    //Act
    var emailer = new Emailer(emailerService);
    emailer.SendBatchEmails();

    //Assert
    emailer.VerifyAllExpectations();
}

在第二个测试中,似乎您想测试如果SendEmail失败则抛出异常。在这种情况下,emailerService更适合作为Stub:

[TestMethod, ExpectedException(typeof(Exception))]
public void Emailer_SendEmailReturnsFalse_ThrowException()
{
    //Arrange
    var emailerService = MockRepository.GenerateStub<IEmailerService>();
    emailerServie.Stub(x => x.SendEmail("", "")).IgnoreArguments().Return(false);

    //Act
    var emailer = new Emailer(emailerService);
    emailer.SendBatchEmails();

    //Assert
    //Expect Exception
    /* Even when I don't have and assert call here, I usually leave a note*/
}