模拟调用异常为 0 次,但我可以正确看到执行的调用

Exception of invocation on the mock was 0 times, but I can see performed invocations correctly

这是我的简化版单元测试

var service = Fixture.Freeze<IService>();
var outerService = Fixture.Create<OuterService>();

var testObject = Fixture.Create<TestObject>();

outerService.Notify(testObject);
Mock.Get(service).Verify(s => s.SendNotification(It.IsAny<String>(), It.IsAny<TestObject>(), null), Times.Once);

注意:

outerService.Notify(testObject)

内部调用

IService.SendNotification(string testObject.Name, testObject, extraObject = null)


以上会导致测试失败,报错:

Expected invocation 1 time,but was 0 times: 
s => s.SendNotification(It.IsAny<String>(), It.IsAny<TestObject>(), null)
No setups configured.

Performed invocations:
IService.SendNotification("testObject", UnitTest.TestObject, null)

我不明白,执行的调用看起来和预期的调用完全一样,这是怎么回事?


编辑

好的,所以如果我在测试中直接调用service.SendNotification 就可以了,但是如果我通过outerService 调用它就不行了?为什么?


更新

抱歉,如果我的问题不够清楚,这里有一些关于如何配置 Fixture 对象的更多细节:

Fixture fixture = new Fixture();
fixture.Customize(new AutoConfiguredMoqCustomization());
fixture.Customize(new SpecimenCustomization());

关于细节,这确实是关于它的,希望它不是我想的复杂场景。

调用 Mock.GetThe received mocked instance was not created by Moq 时会发生该错误。这意味着模拟服务有 No setups configured

鉴于这个简化的假设。

public class OuterService {
    private IService service;

    public OuterService(IService service) {
        this.service = service;
    }

    public void Notify(TestObject testObject) {
        service.SendNotification(testObject.Name, testObject, extraObject: null);
    }
}

public interface IService {
    void SendNotification(string name, TestObject testObject, object extraObject);
}

public class TestObject {
    public string Name { get; set; }
} 

以下测试应该有效

//Arrange
var service = Mock.Of<IService>();
var outerService = new OuterService(service);
var testObject = new TestObject { Name = "testObject" };

//Act
outerService.Notify(testObject);

//Assert
Mock.Get(service).Verify(s => s.SendNotification(It.IsAny<String>(), It.IsAny<TestObject>(), null), Times.Once);

Moq 现在知道服务对象并且可以从上面创建的模拟实例中提取模拟设置。

更新:

意识到您正在使用 AutoFixture,经过一些研究后能够重现您的问题。您需要自定义 AutoFixture 才能使用 Moq.

检查 Auto-Mocking with Moq 如何做到这一点。

以下假设与上述相同。

//Arrange
var fixture = new Fixture();
fixture.Customize(new Ploeh.AutoFixture.AutoMoq.AutoMoqCustomization());

var service = fixture.Freeze<IService>();
var outerService = fixture.Create<OuterService>();
var testObject = fixture.Create<TestObject>();

//Act
outerService.Notify(testObject);

//Assert
Mock.Get(service).Verify(s => s.SendNotification(It.IsAny<String>(), It.IsAny<TestObject>(), null), Times.Once);