Search code examples
.netunit-testingintegration-testingfakeiteasy

FakeItEasy ClearRecordedCalls not working on wrapping fake


I'm using the DI container to create my fakes for integration testing. I'm calling this method for all the interfaces I need to fake in my ConfigureServices function in my Application factory:

public static IServiceCollection FakeWithBaseImplementation<T>(this IServiceCollection services)
     where T : class
{
    // Create a fake for the wrapper class
    var sp = services.BuildServiceProvider();
    var classImplementation = sp.GetService<T>();
    var fake = A.Fake<T>(o => o.Wrapping(classImplementation!));
    services.Remove<T>();
    services.AddTransient(_ => fake);
    return services;
}

After each test, I call this method to reset the state of the fakes:

public void ResetFakeServiceState<TServiceType>()
     where TServiceType : notnull
{
    var service = this.Services.GetRequiredService<TServiceType>();
    if (Fake.IsFake(service))
    {
        Fake.ClearRecordedCalls(service);
    }
}

However, I saw that when wrapping with the implementation, it doesn't create a Fake but a pseudo real instance and I can't seem to ClearRecordedCalls. The behavior is that if I override a method of a service, then I ClearRecordedCalls and then I execute another test, the method will still be override.

The reason I'm using wrapping is that I still want to use the original implementation AND the DI container for the class constructor. I tried using Fake with the CallsBaseMethods() option and it works for calling the base method, but it resolve the DI with Fakes inside the constructor and I want the real classes for real calls to DB and things inside it.

How I found out all this is that if I execute my tests alone, they all pass. But by executing them together, some fails.

UPDATE 1: What I mean by pseudo Fake is that it returns true to Fake.IsFake but inside it is my service without the word Fake in front when I inspect it. I guess that's what wrapping does. But now, how to reset that? enter image description here

I thought about removing it from the DI container, but then, how to add it back?


Solution

  • Since version 8.2.0, we now have the options to call Fake.Reset(object fake). This is all we needed to properly use FakeItEasy in DI situations.