模拟副作用

Wat*_*tap 3 c# unit-testing moq mocking

使用 Moq,是否可以设置模拟属性以使其发生变化?

\n\n

例如,给定:

\n\n
public interface IService // To be mocked.\n{\n    bool IsConnected { get; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

是否可以设置 IService 的模拟以使以下内容通过?

\n\n
var mockService = new Mock<IService>();\n\n// Setup mockService so IsConnected mutates...?\n\nbool before = mockService.Object.IsConnected;\n\nbool after = mockService.Object.IsConnected;\n\nAssert.AreNotEqual(before, after);\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,这个设置并不能解决问题:

\n\n
mockService.SetupGet(service => service.IsConnected).Returns(false);\nmockService.SetupGet(service => service.IsConnected).Returns(true);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这与我的理解是一致的,即 Moq 没有实现记录/回放模型。

\n\n

这是一个更现实的例子:

\n\n
public interface IService // To be mocked.\n{\n    bool IsConnected { get; }\n\n    void Connect(); // Mutates IsConnected.\n}\n\nclass Client // To be tested\n{\n    private readonly IService service;\n\n    public Client(IService service)\n    {\n        this.service = service;\n    }\n\n    public bool DoWork()\n    {\n        if (!service.IsConnected)  // In test, IsConnected should return false.\n        {\n            service.Connect();\n        }\n\n        if (!service.IsConnected) // In test, IsConnected should return true.\n        {\n            return false;\n        }\n\n        // ... yada yada yada more code\n\n        return true;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

I\xe2\x80\x99m 使用起订量 4.0.10827.0。

\n

cad*_*ll0 5

您可以将 Returns 设置为 aFunc<bool>而不是 bool。然后,您将编写该函数以更改其结果。就像是....

bool isConnected = false
var mockService = new Mock<IService>();
// Setup mockService so IsConnected mutates...?
mockService.Setup(s => s.Connect()).Callback(() => isConnected = true);
mockService.SetupGet(s => s.IsConnected).Returns(() => isConnected);

bool before = mockService.Object.IsConnected;

mockService.Object.Connect();

bool after = mockService.Object.IsConnected;

Assert.AreNotEqual(before, after);
Run Code Online (Sandbox Code Playgroud)

但是,根据您的服务的复杂程度,您可能需要考虑制作 FakeService 并使用它而不是模拟。