在编写单元测试时断言 "nothing happened"

Assert that "nothing happened" when writing unit test

在写单元测试的时候,有什么简单的方法可以保证不出意外吗?

由于可能的副作用列表是无限的,添加大量断言以确保在每一步都没有改变似乎是徒劳的,它混淆了测试的目的。

我可能错过了一些框架功能或良好实践。
我正在使用 C#7、.net 4.6、MSTest V1。

编辑: 更简单的示例是测试视图模型的 setter,应该发生两件事:值应该更改并且应该引发 PropertyChanged 事件。 这两件事很容易检查,但现在我需要确保其他属性值没有改变,没有引发其他事件,没有触及系统剪贴板...

您错过了单元测试的要点。他们是"proofs"。你无法从逻辑上证明一个否定的断言,所以即使尝试也没有意义。

每个单元测试中的断言应证明所需的行为已完成。就这些了。

如果我们将问题简化为荒谬,每个单元测试都需要我们断言被测函数没有启动热核war。

单元测试不是您需要执行的唯一一种测试。有功能测试、集成测试、可用性测试等,各有侧重。对于单元测试,重点是证明单个功能的预期行为。因此,如果该函数应该完成两件事,只需断言这两件事都发生了,然后继续。

对您的编辑的一些补充:

Test Driven Development 中,您只编写代码,这将通过测试,仅此而已。此外,您想选择最简单的解决方案来实现此目标。

也就是说,您很可能会从失败的单元测试开始。在你的情况下,你不会在开始时得到一个失败的单元测试。

如果你将它推到极限,当你想检查每一个结果时,你必须检查 format C:\ 没有在你的应用程序中调用。您可能想看看设计原则,例如 KISS-原则(保持简单,愚蠢)。

如果 "check that nothing else happened" 的范围是确保模型的状态没有改变,那么问题就是这种情况。

编写一个辅助函数,在你的事件之前和之后获取模型并比较它们。让它 return 更改的属性,然后您可以断言只有那些您打算更新的属性在 return 列表中。这种助手是可移植的、可维护的和可重用的

检查模型状态是单元测试的有效应用。

确保没有 'bad' 或意外情况发生的方法之一是确保使用依赖注入和模拟的良好实践:

[Test]
public void TestSomething()
{
    // Arrange
    var barMock = RhinoMocks.MockRepository.GenerateStrictMock<IBar>();
    var foo = new Foo(barMock);
    // Act
    foo.DoSomething();
    // Assert
    ...
}

在上面的示例中,如果 Foo 不小心触及 Bar,将导致异常(严格模拟)并且测试失败。这种方法可能不适用于所有测试用例,但可以作为对其他潜在实践的一个很好的补充。

这仅适用于引用透明的语言,例如 Safe Haskell。