在项目中重构单元测试时,我发现了一些应该失败的测试,但由于一些神秘的原因而成功。删除不相关的代码并将所有内容移动到一个方法后,以下最小示例仍然具有原始行为:
[Test]
public void TestThatShouldFail()
{
// Arrange
var mock = MockRepository.GenerateStub<ISomething>();
mock.Stub(wi => wi.SomeProperty).Return(MockRepository.GenerateStub<ISomeProperty>());
mock.SomeProperty.Stub(t => t.SomethingElse).Return(new SomethingElse());
...
// Act
_foo.Foo();
// Assert
mock.AssertWasCalled(wi => wi.SomeProperty.DoSomething());
}
变量mock
永远不会以 Act 部分中运行的代码可用的任何方式传递,公开或导出。仍然,测试通过,这应该意味着在DoSomething
变量的SomeProperty
上调用了mock
方法,这显然是错误的。
这怎么可能发生?
答案 0 :(得分:2)
上面的代码已经是一些调查的结果,所以它只包含与问题及其解决方案相关的行。
罪魁祸首是 Arrange 部分的最后一行。
事实证明, Assert 行并没有真正检查DoSomething
方法是否在SomeProperty
上调用,而是{{1}在SomeProperty
上访问过了!我们实际上是在最后一个 Arrange 行中执行此操作,当时在其上存根方法。
我无法找到任何官方文档,因此我只能假设它只考虑其参数中表达式的第一级,因此不应该传递具有多个级别的表达式成员访问(点)到mock
(或AssertWasCalled
)。
(检查它的正确方法是AssertWasNotCalled
,但此处并不需要。)