Search code examples
c#xunitautofixturefakeiteasy

Injecting a fake concrete class via FakeItEasy and AutoFixture


I've got a class I want to test where a concrete class (MyClient) is being injected.

private readonly MyClient _client;

public Sync(MyClient client)
{
    _client = client;
}

For testing we're using xUnit, AutoFixture and FakeItEasy. This all works quite well when injecting interfaces to a class.

However, when using the following test setup

[Theory]
[AutoFakeData]
public async Task It_should_invoke_client(
    [Frozen]MyClient geoClient,
    [Frozen]ILogger logger,
    Sync sync)
{
    // Act
    await sync.Run(null, logger);

    //Assert
    A.CallTo(() => myClient.SyncAllAsync(A<CancellationToken>.Ignored)).MustHaveHappenedOnceExactly();
}

The faked GeoClient isn't injected to the sync parameter. The created sync is stating the injected MyClient isn't a Faked object.

System.ArgumentException : Object 'Some.Namespace.MyClient' of type Some.Namespace.MyClient is not recognized as a fake object.

When debugging through the sync, I see this is correct. A 'normal' MyClient has been injected to the system under test.

From what I understand from the documentation, this should just work. I'm probably missing some obvious step, but fail to find it.


Solution

  • AutoFakeItEasy only provides fakes if the requested specimen is of a type that is either abstract or an interface. See FakeItEasyRelay:

    return type.GetTypeInfo().IsAbstract || type.GetTypeInfo().IsInterface;
    

    It appears that you could override this by providing a custom ISpecimenBuilder relay, but I've not tried.