Home > Back-end >  Moq: Mocking an interface of abstract base class of a controller
Moq: Mocking an interface of abstract base class of a controller

Time:10-05

My problem: I want to unittest a controller. This controller has a constructor that includes a repository. Repositories are named like SomethingRepository. SomethingRepository inherits from abstract class BaseRepository<ReadModel, Dto, Filter>. BaseRepository inherits from interface IRepository<ReadModel, Dto, Filter>.

When I want to mock SomethingRepository using Moq, I will need to mock the interface, as far as I understand, since mocking a class will demand an empty constructor which SomethingRepository and BaseRepository don't have. (I don't want to add one)

So, I have tried

Mock.Of<
   IRepository<
       SomeReadModel,
       SomeDto,
       SomeFilter>
>();

However, when I try to assign this mock (with a cast) to a variable of type SomethingRepository, I get an InvalidCastException:

System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.IRepository`3Proxy' to type 'Repositories.SomeRepository'.

How do I fix this?

CodePudding user response:

Every SomeRepository is a IRepository<SomeReadModel, SomeDto, SomeFilter>, but not every IRepository<SomeReadModel, SomeDto, SomeFilter> is a SomeRepository. If your controller injects a SomeRepository, you have to provide something which is (or inherits from) the SomeRepository class.

The solution is to change your controller so that it injects a IRepository<SomeReadModel, SomeDto, SomeFilter> instead.

CodePudding user response:

The constructor of SomeController has the following signature which takes in an IRepository:

public SomeController(IRepository<ReadModel, Dto, Filter> repository)
    : base(repository)

In my test, I was trying to do cast this to the concrete repository:

SomeRepository repository = (SomeRepository) Mock.of<IRepository<ReadModel, Dto, Filter>>;

new SomeController(repository);

Instead, I need to pass the repository interface into the controller, not the concrete class:

IRepository<Something> repository = Mock.of<IRepository<ReadModel, Dto, Filter>>;

new SomeController(repository);
  • Related