0

我正在关注 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(); });
    }

}

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

4

2 回答 2

1

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

使用 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 的调用命名不当。我想这只是为了演示/Stackoverflow 问题。但我建议您在未来提供一个真实世界的示例,其中包含“Do”“Something”以外的真实名称,从 TDD 的角度来看,当您根据需求设计小型系统时,具有模糊名称并没有帮助。

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

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

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

于 2013-10-06T03:13:45.597 回答
0

当我测试类似的方法时

  • 我不写测试,不调用 x.Do()
  • 我检查是否抛出了异常,并且 x.Do() 在一次测试中没有被调用,因为这两个断言与同一流相关。
于 2013-10-05T23:16:52.190 回答