Implicit Creation Options

While it's possible to provide explicit creation options, this can sometimes be tedious. Sometimes you want to have every Fake of a particular type start with some basic configuration, using a FakeOptionsBuilder. Here's an example:

public class RobotRunsAmokEventFakeOptionsBuilder : FakeOptionsBuilder<RobotRunsAmokEvent>
{
    protected override void BuildOptions(IFakeOptions<RobotRunsAmokEvent> options)
    {
        options.ConfigureFake(fake =>
        {
            A.CallTo(() => fake.CalculateTimestamp())
                .Returns(new DateTime(1997, 8, 29, 2, 14, 03));
            robotRunsAmokEvent.ID = Guid.NewGuid();
        });
    }
}

This will ensure that any new RobotRunsAmokEventFakeOptionsBuilder will have an appropriate date applied and will have a unique ID.

In addition to ConfigureFake, any explicit creation option can be used in BuildOptions, including implementing interfaces, providing constructor arguments, and more.

How it works

FakeItEasy uses classes that implement the following interface to configure Fakes:

public interface IFakeOptionsBuilder
{
    bool CanBuildOptionsForFakeOfType(Type type);
    void BuildOptions(Type typeOfFake, IFakeOptions options);
    Priority Priority { get; }
}

When FakeItEasy creates a Fake, it looks at all known IFakeOptionsBuilder implementations for which CanBuildOptionsForFakeOfType returns true. Then it passes an empty options object to BuildOptions. If multiple implementations match, the one with the highest Priorityis used.

If all that's needed is a Fake Options Builder that configures a single explicit type, extending abstract class FakeOptionsBuilder<T>: IFakeOptionsBuilder is preferred, as was done above. This abstract class provides default implementations of Priority and CanBuildOptionsForFakeOfType (although the Priority can be overridden if needed). If you want to configure a vaierty of Fake types, you may prefer to extend IFakeOptionsBuilder directly. For example, if you wanted all Fakes to be Strict, you might write something like this:

class MakeEverythingStrictOptionsBuilder : IFakeOptionsBuilder
{
    public bool CanBuildOptionsForFakeOfType(Type type)
    {
        return true;
    }

    public void BuildOptions(Type typeOfFake, IFakeOptions options)
    {
        options.Strict();
    }

    public Priority Priority
    {
        get { return Priority.Default; } // equivalent to value 0
    }
}

This method provides additional power, in that the Fake Options Builder can be applied to more types, but it sacrifices compile-time typesafety. Of course, it's possible to perform more sophisticated analysis on the types, perhaps having CanBuildOptionsForFakeOfType accept only types whose name match a pattern. In this way, conventions-based faking could be accomplished.

Note that once the type of Fake being created is identified, say as FakedType, it's possible to cast options to a IFakeOptions<FakedType> and operate on it, but the FakedType must be the exact type being faked, not just something in the inheritance tree.

How does FakeItEasy find the Fake Options Builders?

On initialization, FakeItEasy looks for Discoverable Extension Points, including Fake Options Builders.