I have a complex legacy application that I'm not allowed to refactor. I am trying to write tests and don't want to repeat the same set up multiple times. I created a helper class which holds the mocks (TargetMocks) with methods to set up most of the logging arrange statements so I could focus the test on a specific aspect of the system under test.
I've created an example NUnit test with a sample set of classes and Interfaces. All but one of the tests work and I don't understand why the failing test fails. It has the same exact Mock.Arrange statements that are executed in the same order. The only difference is the failing test has the Mock.Arrange statements in the test method while the working test has the Mock.Arrange methods in the TestMocks helper class.
public class TargetMocks
{
public ILogger Logger { get; } = Mock.Create<
ILogger
>();
public IUtility Util { get; } = Mock.Create<
IUtility
>();
public StringBuilder LoggerBuilder {get;} = new StringBuilder();
public void SetupMocks()
{
Mock.Arrange(() => Logger.Info(Arg.AnyString))
.DoInstead((string msg) =>
{
LoggerBuilder.AppendLine(msg);
});
}
public Target CreateTarget()
{
var sut = new Target();
Mock.Arrange(() => sut.Logger).Returns(Logger);
Mock.Arrange(() => sut.Util).Returns(Util);
return sut;
}
public Target CreateTargetAndSetupUtil()
{
var sut = new Target();
Mock.Arrange(() => sut.Logger).Returns(Logger);
Mock.Arrange(() => sut.Util).Returns(Util);
//Mock.Arrange(() => mock.Util.ChangeState(Arg.AnyInt, Arg.AnyString)).MustBeCalled();
Mock.Arrange(() => Util.SaveState(Arg.AnyInt, Arg.AnyString)).MustBeCalled();
return sut;
}
}
The following test fails
[Test()]
public void x3TestWidgetProcessUtilMethods_Test_TestUsesSeperateClassMocksAndCreatesSUT_But_Fails()
{
var expectedLog =
"target message 1\r\n" +
"Message 1\r\n" +
"Message 3\r\n" +
"target message 3\r\n";
var mock = new TargetMocks();
mock.SetupMocks();
var sut = mock.CreateTarget();
Mock.Arrange(() => mock.Util.ChangeState(Arg.AnyInt, Arg.AnyString)).MustBeCalled();
Mock.Arrange(() => mock.Util.SaveState(Arg.AnyInt, Arg.AnyString)).MustBeCalled();
sut.Process();
var log = mock.LoggerBuilder.ToString();
Assert.AreEqual(expectedLog, log, log);
Mock.Assert(mock.Util);
}
But this test works.
[Test()]
public void x3aTestWidgetProcessUtilMethods_Test_TestUsesSeperateClassMocksAndCreatesSUTAndSetsUpUtilMock_WorksAsExpected()
{
var expectedLog =
"target message 1\r\n" +
"Message 1\r\n" +
"Message 3\r\n" +
"target message 3\r\n";
var mock = new TargetMocks();
mock.SetupMocks();
var sut = mock.CreateTargetAndSetupUtil();
sut.Process();
var log = mock.LoggerBuilder.ToString();
Assert.AreEqual(expectedLog, log, log);
Mock.Assert(mock.Util);
}
- Why does the first test fail?