【问题标题】:Verifying a method call still passes when a failure is expected in unit test当单元测试中预期失败时,验证方法调用仍然通过
【发布时间】:2012-12-15 13:21:22
【问题描述】:

我刚开始在单元测试中使用 Moq,但遇到单元测试通过的问题 - 我认为它不应该通过。

我有两个对象,一个将数据发送到队列,另一个实现INotifier,如果发送失败,则调用它,它们看起来像这样(为简洁起见):

public class EmailNotifier : INotifier
{
    public void Notify(string message) 
    {
        // sends the notification by email
    }
}

public class Despatcher
{
    public void Despatch(int batchNumber, INotifier failureNotifier)
    {
        try
        {
            if (batchNumber.Equals(0)) throw new InvalidOperationException("Error message");
        }
        catch (InvalidOperationException ex)
        {
            failureNotifier.Notify(ex.ToString());

            throw ex;
        }
    }
}

我正在对Despatcher 进行单元测试,以专门验证Notify 在提供的INotifier(我在嘲笑)失败时被调用(我故意迫使Despatcher 失败)传递一个 0 批号)。我这样设置我的模拟:

[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void Despatcher_notifies_on_failure()
{
    var mockNotifier = new Mock<EmailNotifier>();
    mockNotifier.Setup(n => n.Notify(It.IsAny<string>())).Verifiable();

    var despatcher = new Despatcher();
    despatcher.Despatch(0, mockNotifier.Object);

    mockNotifier.Verify(n => n.Notify(It.IsAny<string>()), Times.Once());
}

这很好地通过了测试,这是预期的,因为批号为 0 会引发异常,导致 INotifier 调用 Notify(当我逐步完成测试时,一切都按预期工作)。

所以,我继续注释掉 failureNotifier.Notify(ex.ToString()) 行并再次运行测试 - 通过了吗?我不确定我是否正确设置和验证,因为我现在只使用 Moq 大约 2 个小时,但我认为我理解正确,但这让我有点失望。我希望这个测试失败,因为我特别想确保在失败的情况下调用Notify - 任何人都可以在这里看到任何明显的错误吗?提前感谢您一如既往的帮助。

【问题讨论】:

  • 您是否尝试过使用 Times.Exactly(1)?
  • @FelicePollano 我没有,但只是有,它仍然可以通过。我还应该提到我已经完成了清理项目的明显工作,以确保不使用较旧的(没有注释 Notify 行),并且单步执行我可以看到注释掉的版本正在正确使用。跨度>
  • 从我的角度来看,您的测试将通过 co,您期望出现 InvalidOperationException 类型的异常并且它正在被抛出。如果您重新评论failureNotifier.Notify(ex.ToString());,您的测试应该会失败。因为那里有 Notify();方法调用没有被调用。
  • @Syneryx 这是我有点困惑的地方。我希望测试失败,除非测试中的所有内容都通过 - 据我所知,我正在测试是否引发了某个异常并且 Notify 方法的调用已得到验证。

标签: c# unit-testing moq


【解决方案1】:

您的测试永远不会进入验证部分。为什么?这一行

despatcher.Despatch(0, mockNotifier.Object);

抛出异常,由ExpectedException 属性消耗并测试endsmockNotifier.Verify 行永远不会执行。

你想要的是两个 unit 测试,而不是:

  • 一个测试通知程序在异常时被调用(使用.Verify)。请注意,您必须将 .Despatch 调用包装到 try { } catch { } 中,以便忽略该异常。
  • 其次,检查异常是否被重新抛出(使用ExpectedException

【讨论】:

  • 当然!我只是假设我正在测试抛出的异常并且我的Notify 正在被调用。这是一种享受,谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多