The right way to mock (with moq) methods that return mocked objects?
-
10-07-2019 - |
Question
Which of these is correct?
var mockLogger = new Mock<EntLibLogger>();
mockLogger.Setup(i => i.CreateTracer(It.IsAny<string>()))
.Returns((string operationName) =>
{
var mockTracer = new Mock<EntLibTracer>(operationName);
mockTracer.Setup(i => i.IsTracingEnabled())
.Returns(true);
mockTracer.CallBase = true;
return mockTracer.Object;
});
mockLogger.CallBase = true;
//EntLibLogger.Current is a singleton that is shared across multiple threads.
//This Initialize method will set EntLibLogger.Current to the mocked instance
//instead of the default (non-mocked) configuration
EntLibLogger.Initialize(mockLogger.Object);
OR
var mockTracer = new Mock<EntLibTracer>(operationName);
mockTracer.Setup(i => i.IsTracingEnabled())
.Returns(true);
mockTracer.CallBase = true;
var mockLogger = new Mock<EntLibLogger>();
mockLogger.Setup(i => i.CreateTracer(It.IsAny<string>()))
.Returns(mockTracer.Object);
mockLogger.CallBase = true;
EntLibLogger.Initialize(mockLogger.Object);
I believe the first approach is correct but I am not sure if Moq might be doing some magic under the hood and just wanted to validate :)
Solution
I guess the main question is what you want to happen if it calls CreateTracer
twice. In the first version you'll get two different mock tracers; in the second you'll get the same one twice.
The second version is what I've usually used in jMock, EasyMock and Rhino.Mocks - but I don't have any experience with Moq, so it may be more idiomatic to use the first form there. The second is simpler though, IMO :)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow