Mocking side effects
c#, mocking, moq, unit-testing
Solution
You can set Returns to a `Func<bool>` instead of a bool. You would then have write that func such that it changes its result. Something like....
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);
However, depending on how complicated your serivce gets, you may want to consider making a FakeService and use that instead of mocking.
Problem
With Moq, is it possible to setup a mocked property so that it mutates? For example, given: ``` public interface IService // To be mocked. { bool IsConnected { get; } } ``` Is it possible to setup a mock of IService such that the following passes? ``` var mockService = new Mock<IService>(); // Setup mockService so IsConnected mutates...? bool before = mockService.Object.IsConnected; bool after = mockService.Object.IsConnected; Assert.AreNotEqual(before, after); ``` Certainly this setup doesn’t do the trick: ``` mockService.SetupGet(service => service.IsConnected).Returns(false); mockService.SetupGet(service => service.IsConnected).Returns(true); ``` That is consistent my understanding that Moq does not implement the record/playback model. Here is a little more realistic example: ``` public interface IService // To be mocked. { bool IsConnected { get; } void Connect(); // Mutates IsConnected. } class Client // To be tested { private readonly IService service; public Client(IService service) { this.service = service; } public bool DoWork() { if (!service.IsConnected) // In test, IsConnected should return false. { service.Connect(); } if (!service.IsConnected) // In test, IsConnected should return true. { return false; } // ... yada yada yada more code return true; } } ``` I’m using Moq 4.0.10827.0.