FakeItEasy – Gotchas with builder pattern

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.

Leave a comment