正确测试某个方法在某些情况下什么都不做

Correctly testing that a method does nothing under certain cicrumstances

我的单元测试代码和 SonarQube 运行 有点麻烦。

我有以下简单测试:

    [TestMethod]
    public void TestFormat_Null()
    {
        _sut.Format(null);
    }

    public void Format(IPhone phoneNumber)
    {
        if (phoneNumber == null) return;
        FormatNumber(phoneNumber);
        FormatAreaCode(phoneNumber);
        FormatCountryCode(phoneNumber);
    }

这里的要求是,如果传入 null,该方法将什么都不做,因为没有要格式化的东西,也不会因异常而崩溃。

现在我们遇到的问题是我们的 SonarQube 抱怨说这是一个没有任何断言的测试。

有没有更好的方法来声明一个测试,该测试测试一个没有做任何事情的方法,或者在这种情况下应该简单地忽略 SonarQube 警告?

没有失败(并且不是不确定的)的测试就是通过的测试。

一些测试库如 NUnit 包括“Assert.DoesNotThrow”,其他的则不包括,如 MsTest 和 xUnit。从技术上讲,在每个测试结束时已经有一个隐式 Assert.DoesNotThrow。

我建议您考虑一下这里正在测试的内容。如果你传递 null 那么 SUT 会发生什么?它是否将某些 属性 设置为 null 或空字符串,谁使用了 属性?当然,Format() 确实 做了一些事情!

因此,如果我们通过查看它们的 return 值来测试纯函数,我们可以通过查看它们的实际作用来测试 void 方法——它们的 副作用 .

[TestMethod]
public void TestFormat_Null()
{
    _sut.Format(null);
    Assert.equal(string.empty, _sut.PrintInputText())
}

这可能证明是一个更有价值的测试,比像 Assert.True(true) 这样的变通方法更好......并且也许证明 SonarCube 的警告毕竟仍然有用。

我在 FluentAssertions 中找到了解决方案。

我的新代码将对 _sut 的旧调用包装在一个操作中,并使用 Fluent Assertions Should Not Throw 机制。

这是一个优雅的解决方案,因为我们已经在使用 FluentAssertions。我只是从来没有意识到它提供的 Should Not Throw 断言。直到现在我才知道 Should Throw。