AssertWasCalled 传递未使用的变量

AssertWasCalled passes on unused variable

在重构项目中的单元测试时,我发现一些本应失败但由于某种神秘原因而成功的测试。删除不相关的代码并将所有内容移至一个方法后,以下最小示例仍然具有原始行为:

[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 部分中的代码 运行 的方式传递、公开或导出。仍然,测试通过,这应该意味着在mock变量的SomeProperty上调用了DoSomething方法,这显然是错误的。

怎么会这样?

上面的代码已经是一些调查的结果,因此它只包含与问题及其解决方案相关的行。

罪魁祸首是 Arrange 部分的最后一行。

事实证明,Assert 行并没有真正检查是否在 SomeProperty 上调用了 DoSomething 方法,但是 SomeProperty 是否在 mock! 上被访问了,我们实际上是在最后的 Arrange 行中完成的,当在其上添加一个方法时。

我找不到它的任何官方文档,所以我只能假设它只考虑其参数中表达式的第一级,所以 不应该传递具有多个级别的表达式成员对 AssertWasCalled(或 AssertWasNotCalled)的访问权限(点)。

(检查它的正确方法是 mock.SomeProperty.AssertWasCalled(wi => wi.DoSomething()),但这里不需要。)