正确测试方法在某些情况下啥都不做

Posted

技术标签:

【中文标题】正确测试方法在某些情况下啥都不做【英文标题】:Correctly testing that a method does nothing under certain cicrumstances正确测试方法在某些情况下什么都不做 【发布时间】:2021-08-07 13:21:57 【问题描述】:

我的单元测试代码和 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 警告?

【问题讨论】:

Format() 中是否有您可以测试的副作用?或者您检查调用_sut.Format(null) 不会引发异常... @mu88 没有副作用。我只想测试代码不会引发异常。 AFAIK MSTestV2(我们使用的框架)没有针对“DoesNotThrow”案例的明确断言。 你说得对,MSTest ootb 没有这样的功能——但其他框架有,比如Fluent Assertions——无论如何我强烈推荐你使用***断言框架????但是当然,即使使用 MSTest,您也可以引入布尔变量 hasFailed,将调用封装在 try-catch 中,将 hasFailed = true 设置在 catch 中,最后设置为 Assert.IsFalse(hasFailed) @mu88 查看我发布的答案。这是我通过 FluentAssertions 确定的解决方案 :) 【参考方案1】:

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

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

我建议您考虑这里要测试的内容。如果传递 null 那么 SUT 会发生什么?它是否将某些属性设置为 null 或者可能是一个空字符串,以及谁使用该属性?当然 Format() 一些事情!

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

[TestMethod]
public void TestFormat_Null()

    _sut.Format(null);
    Assert.equal(string.empty, _sut.PrintInputText())

这可能证明是一个更有价值的测试,比 Assert.True(true) 之类的解决方法更好......也许可以证明 SonarCube 的警告毕竟仍然有用。

【讨论】:

我在原始问题中添加了 Format 的定义。如您所见,它实际上对传入 null 没有任何作用。 @PixieChrysalis Format() 方法确实有一个整体的副作用。例如,如果我用“null”格式化我的电话号码,那么之后的预期电话号码是什么?和原来一样吗?如果是这样,您可以断言。 类似于 x = x + 0 做了一些事情:x 保持 x,这是重要的部分。【参考方案2】:

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

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

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

【讨论】:

以上是关于正确测试方法在某些情况下啥都不做的主要内容,如果未能解决你的问题,请参考以下文章

Windows 上的 Electron Packager 啥都不做

IOS Ad Hoc 分发链接啥都不做

为啥 Java 的 concat() 方法啥都不做?

为啥 Java 的 concat() 方法啥都不做?

如何创建一个在 React 中啥都不做的函数

为啥#后跟一个数字似乎在C plus plus中啥都不做