K.Z
K.Z

Reputation: 5075

How to mock object where single interface is implemented by multiple classes

I have one interface with multiple classes implementation. I have registered them in Autofac Container. My PaymentService class takes two parameters where one of them can implement multiple classes. How to mock to specific class??

Interface

public interface IAccountDataStorage
{
    Account GetAccount(string accountNumber);
    void UpdateAccount(Account account);
}

Implemented classes

public class BackupAccountDataStore : IAccountDataStorage
{
     ...
}

public class AccountDataStore : IAccountDataStorage
{
     ...
}

Register in Autofac container

 builder.RegisterType<AccountDataStore>().Keyed("defaultAccountStorage", typeof(IAccountDataStorage));
 builder.RegisterType<BackupAccountDataStore>().Keyed("backupAccountStorage", typeof(IAccountDataStorage));

To Resolve Interface of the specific class

var a = buildContainer.ResolveKeyed<IAccountDataStorage>("defaultAccountStorage");
var b = buildContainer.ResolveKeyed<IAccountDataStorage>("backupAccountStorage");

Test class

public class MakePaymentTest
{
    private readonly PaymentService sut;
    private readonly Mock<IAppAmbientState> mockAppAmbientState = new Mock<IAppAmbientState>();
    //private readonly Mock<IAccountDataStorage> mockAccountDataStorage = new Mock<IAccountDataStorage>();


    public MakePaymentTest()
    {
        mockAppAmbientState.Object.AppSettingsRepository = new App.SharedKernel.Values.AppConfiguration
        {
            DataStoreType = "Backup"
        };

        //Need help here
        sut = new PaymentService(mockAppAmbientState.Object, ???????); // let say I want mock AccountDataStore here...
    }

    [Fact]
    public void MakePayment_Should_ReturnTypeOf_MakePaymentResult()
    {
        //Arrange
        var fixture = new Fixture();
        var mockMakePaymentRequest = fixture.Create<MakePaymentRequest>();


        //Act
        var actualDataResult = sut.MakePayment(mockMakePaymentRequest);

        //Assert

    }

Upvotes: 0

Views: 1031

Answers (1)

Athanasios Kataras
Athanasios Kataras

Reputation: 26362

You do not Mock a specific implementation. You mock return values

sut = new PaymentService(mockAppAmbientState.Object, ???????); // let say I want mock AccountDataStore here...

What you must do, is make the first and second mock objects, return the proper values for your unit test to follow the needed code paths.

The concrete implementations of the classes, will be tested in their own classes.

The whole idea of the following line, is to use the abstraction and handle the return values. So any link to the actual concrete implementation, beats the point of mocking in the first place.

private readonly Mock<IAccountDataStorage> mockAccountDataStorage = new Mock<IAccountDataStorage>();

Upvotes: 2

Related Questions