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);