繁体   English   中英

如何在引发异常的同时声明模拟状态

[英]how to assert mock state simultaneous with thrown exception

我正在跟踪TDD并遇到一个问题:如果我使一项测试成功,则另外两项会由于抛出异常而失败。 好吧,我想抛出异常,但我也想验证其他行为。 例如:

public class MyTests {

    [Fact]
    public void DoSomethingIsCalledOnceWhenCheckerIsTrue() 
    {
        var checker = new Mock<IChecker>();
        var doer = new Mock<IDoer>();

        checker.Setup(x => x.PassesCheck).Returns(true);
        var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);

        sut.CheckAndDo();

        checker.VerifyGet(x => x.PassesCheck, Times.Once());
        doer.Verify(x => x.Do(),Times.Once());
    }

    [Fact]
    public void DoSomethingIsNeverCalledWhenCheckerIsFalse() 
    {
        var checker = new Mock<IChecker>();
        var doer = new Mock<IDoer>();

        checker.Setup(x => x.PassesCheck).Returns(false);
        var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);

        sut.CheckAndDo();

        doer.Verify(x => x.Do(),Times.Never());
    }

    [Fact]
    public void ThrowCheckDidNotPassExceptionWhenCheckDoesNotPass()
    {
        var checker = new Mock<IChecker>();
        var doer = new Mock<IDoer>();

        checker.Setup(x => x.PassesCheck).Returns(false);
        var sut = new ThingThatChecksAndDoes(checker.Object,doer.Object);

        Assert.Throws<CheckDidNotPassException>(() => { sut.CheckAndDo(); });
    }

}

我要解决这个问题有哪些选择? 如果有的话,什么是“首选”选择?

您的第一个和第二个测试通过。 然后,当您添加第三个测试时,其余测试将失败!

有TDD

“避免更改已通过的现有测试。而是添加新测试。仅在用户需求更改时才更改现有测试。”

我还假设您的SUT(被测系统)如下

  public void CheckAndDo() {
        var b = _checker.PassesCheck;
        if (b) {
            _doer.Do();
        }

        throw new CheckDidNotPassException();
    }

在您的SUT中,当您抛出新异常时,显然,它会以实现执行逻辑的方式影响其余行为。

因此,这里的选择是更改现有测试。

给它一个命名合理的测试方法,同时声明异常和验证。

    [Test]
    public void CheckAndDo_WhenPassesCheckTrue_DoCalledOnlyOnceAndThrowsCheckDidNotPassException()
    {
        var checker = new Mock<IChecker>();
        var doer = new Mock<IDoer>();

        checker.Setup(x => x.PassesCheck).Returns(true);
        var sut = new ThingThatChecksAndDoes(checker.Object, doer.Object);

        Assert.Throws<CheckDidNotPassException>(() => { sut.CheckAndDo(); });
        doer.Verify(x => x.Do(), Times.Once());
    }

您需要考虑的其他事项:

一种。 TDD可产生良好的单元测试。 良好的方法,可读,可维护且值得信赖的单元测试。 您的测试方法名称和对SUT的调用命名不正确。 我想这只是针对demo / Stackoverflow的问题。 但是我建议将来为您提供一个真实世界的示例,其中包含“ Do”以外的其他真实名称。“某些东西”从TDD的角度来看,具有歧义的名称无济于事,因为您是根据需求来设计小型系统的。

b。 发布正确的代码。 在您的第一个测试中,您通过了模拟类型

   var checker = new Mock<IChecker>();
   var doer = new Mock<IDoer>();
   var sut = new ThingThatChecksAndDoes(checker, doer);

您应该传递实例,例如(checker.Object)

当我测试类似方法

  • 我不编写测试,即未调用x.Do()
  • 我检查是否抛出异常,并且在一次测试中未调用x.Do(),因为这两个断言与同一流程相关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM