Tom*_*han 11 unit-testing side-effects
任何代码都可以提供副作用.大多数情况下,副作用可能是设计糟糕和/或需要重构的标志,但在进行单元测试时,我发现很难对其进行测试.请考虑以下示例:
[Test]
public void TrimAll_Removes_All_Spaces()
{
// Arrange
var testSubject = "A string with lots of space";
var expectedResult = "Astringwithlotsofspace";
// Act
var result = testSubject.TrimAll();
// Assert
Assert.AreEqual(expectedResult, result);
}
Run Code Online (Sandbox Code Playgroud)
测试以下扩展:
public static string TrimAll(this string str)
{
PokeAround();
return str.Replace(" ", "");
}
Run Code Online (Sandbox Code Playgroud)
测试将通过,但没有后卫的副作用.呼叫的影响PokeAround
将完全被忽视.
鉴于你不知道是什么PokeAround
- 它可能是任何东西! - 你怎么写一个防范它的测试?它可能吗?
澄清:
关于PokeAround
完全未知是一个非常不可能的场景,有一些评论,因为我们在编写测试时有源代码.我问这个问题的原因是,找到一种方法来防止后来添加的副作用.也就是说,当我编写测试时,我可能会将exension方法看起来像这样:
public static string TrimAll(this string str)
{
return str.Replace(" ", "");
}
Run Code Online (Sandbox Code Playgroud)
测试通过,一切都很好.然后,一个月后,当我正在度假时,一位同事加了PokeAround
电话.我希望我已经写过的测试失败,因为他做了.
Pét*_*rök 12
这就是所谓的检测中有效合作与遗留代码.也就是说,感知调用测试方法的效果.
鉴于你不知道PokeAround是什么 - 它可能是任何东西!
由于我们正在谈论的单元测试,这应该几乎是真实的-单元测试是白盒测试测试和代码是(应该是)那里为您检查.除非它在某个闭源第三方库中,在这种情况下你不需要测试它不能按定义进行单元测试(也许你需要功能/验收测试,但这是一个完全不同的问题......) .
更新:所以你想确保未来对你的单元测试方法的改变永远不会有任何意想不到的副作用?我觉得你
你不能,因为没有明智的方法来检测现实生活(非平凡)程序中方法调用缺乏副作用.你正在寻找的是一些检查,整个宇宙的状态除了这个和这个小东西之外没有改变.即使从一个不起眼的程序的角度来看,这个宇宙也是巨大的.方法调用可以创建/更新/删除任意数量的本地对象(其中许多甚至无法从单元测试环境中看到),触摸可用本地/网络文件系统上的文件,执行数据库请求,进行远程过程调用. ..
你不应该这样做,因为你的同事要做出未来的改变来照顾他/她改变的单位测试.如果您不相信这会发生,那么您会遇到人员或流程问题,而不是单元测试问题.