My mocking library of choice is FakeItEasy. Earlier when I was creating test for my implementation of a method that called some methods on a builder, I didnt get the results I expected. My setup was a follows
public interface IBuilder
{
IBuilder BuildPartOne();
IBuilder BuildPartTwo();
Assembled Build();
}
public class Builder : IBuilder
{
public Assembled Build()
=> new Assembled("I have been faked away");
public IBuilder BuildPartOne()
{
return this;
}
public IBuilder BuildPartTwo()
{
return this;
}
}
public class Machine
{
private IBuilder _builder;
public Machine(IBuilder builder)
=> _builder = builder;
public Assembled BuildAllThings()
=> _builder
.BuildPartOne()
.BuildPartTwo()
.Build();
}
public class Assembled
{
public string Message {get;}
public Assembled(string message)
{
Message = message;
}
}
I then had my arrange part of my test like this
var fakeBuilder = A.Fake<IBuilder>();
A.CallTo(() => fakeBuilder.Build()).Returns(new Assembled("I was just built"));
var machine = new Machine(fakeBuilder);
var assembled = machine.BuildAllThings();
After this I expected that I would get my Assembled-object back with the property Message populated with my text “I was just built”, but instead I got and object with no value in the Message property. It took a while before I realized that I hadnt setup all the builder method calls, so they simply returned new faked IBuilder object, which in turn made the Build method return a faked Assembled object. The solution was simply to tell FakeItEasy to always return my faked Builder object when a method returned an IBuilder. When I added
A.CallTo(fakeBuilder).WithReturnType<IBuilder>().Returns(fakeBuilder);
to my arrange part my test worked as expected.