How to make any instance creation a fake (FakeItEasy)?

I have this block of code that I would like to test

class SearchEngine
{
    public void Search()
    {
        var module = new SearchModule();
        module.Search();
    }
}

I have simplified it but I cannot provide a searchmodule instance as a parameter of the function Search, nor as a constructor parameter of the class SearchEngine.

Is there a way to insure that the module object will be a fakeiteasy fake when I write my unit test?

I would like to be able to do some CallTo verifications to the module object, notably that module.Search() was called when we call Search()


Solution 1:

Is there a way to insure that the module object will be a fakeiteasy fake when I write my unit test?

No, it's not possible, at least not with the current shape of your code. FakeItEasy can't intercept instance creation using new.

If you want to fake something, it has to be provided somehow to the system under test. The SUT can't create it itself.

I cannot provide a searchmodule instance as a parameter of the function Search, nor as a constructor parameter of the class SearchEngine

Could you inject a factory instead? Something like this:

public interface ISearchModuleFactory
{
    SearchModule Create();
}


class SearchEngine
{
    private readonly ISearchModuleFactory _searchModuleFactory;

    public SearchEngine(ISearchModuleFactory searchModuleFactory)
    {
        _searchModuleFactory = searchModuleFactory;
    }

    public void Search()
    {
        var module = _searchModuleFactory.Create();
        module.Search();
    }
}

You could then test SearchEngine like this:

// Arrange
var factory = A.Fake<ISearchModuleFactory>();
var module = A.Fake<SearchModule>();
A.CallTo(() => factory.Create()).Returns(module);
var searchEngine = new SearchEngine(factory);

// Act
searchEngine.Search();

// Assert
A.CallTo(() => module.Search()).MustHaveHappened();