Given the following code
public class Entity
{
public string Name { get; set; }
public string Status { get; set; }
}
public interface IRepository
{
void InsertEntity(Entity entity);
void UpdateEntity(Entity entity);
}
public class Processor
{
private IRepository _repository;
public Processor(IRepository repository)
{
_repository = repository;
}
public void Execute(string name)
{
var entity = new Entity() { Name = name, Status = "Initialized" };
_repository.InsertEntity(entity);
// do other things with the entity
entity.Status = "Processed";
_repository.UpdateEntity(entity);
}
}
I could write a unit test to verify if the repository is called inside the Execute method, saving the value of the entity with the method InsertEntity. In other words, I'd like to make sure that when InsertEntity is called, the value of Status property of the entity is "Initialized". So my unit test would be like this:
[TestMethod]
public void ShouldSaveEntityWithStatusInitialized()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
processor.Execute("test");
mock.Verify(m => m.InsertEntity(It.Is<Entity>(e => e.Status == "Initialized")), Times.Once()); // fail
}
However, this code fails even calling InsertEntity method with Status = "Initialized" (I've debugged that). I think it's because the entity object is changed during the execution of Execute method (at the end the Status property is changed to "Processed") and Moq verifies the call against the changed object. In fact, this other unit test works well.
[TestMethod]
public void ShouldUpdateEntityWithStatusProcessedAtTheEnd()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
processor.Execute("test");
mock.Verify(m => m.InsertEntity(It.Is<Entity>(e => e.Status == "Processed")), Times.Once());
}
The only way I found to make my first unit test works is using the following workaround. I save the value of Status property using a callback feature of Moq, and assert that later.
[TestMethod]
public void ShouldSaveEntityWithStatusInitialized_withWorkaround()
{
var mock = new Mock<IRepository>();
var processor = new Processor(mock.Object);
string status = string.Empty;
mock.Setup(m => m.InsertEntity(It.IsAny<Entity>())).Callback((Entity e) => status = e.Status);
processor.Execute("test");
Assert.AreEqual("Initialized", status);
}
But I didn't like that. I would like to know if there's a way to make Moq verify the calls made to the mock object during the execution of the STU (system under test), not after all execution is done.
Thanks