How do I trick the interface with Moq or NInject Mocking Kernel

I just made my way through questions and blogs about ridicule and dependency injection. Come to the conclusion, I just need to make fun of the interface that is consumed by the client. I look forward to testing a simple use case without a clue.

the contract

public Interface IApplicationService { bool DeleteApplication(int id); ApplicationDto AddApplication(ApplicationDto application); IEnumerable<ApplicationDto> GetApplications(); } 

Implementation (I'm going to make fun)

 public Class ApplicationService:IApplicationService { private EntityFrameworkRepo repo; public ApplicationService() { repo = new EntityFrameworkRepo(); } public ApplicationDto Add(ApplicationDto dto) { //add to dbcontext and commit } } 

Mutable code

 [Test(Description = "Test If can successfully add application")] public void CanAddApplication() { //create a mock application service var applicationService = new Mock<IApplicationService>(); //create a mock Application Service to be used by business logic var applicationDto = new Mock<ApplicationDto>(); //How do i set this up applicationService.Setup(x => x.GetApplications()).Returns(IEnumerable<applicationDto.Object>); } 

And I'm sure that I need to test the business logic, and not mock it. So what exactly do I need to do to check my ApplicationService , but then save the entity structure.

btw talk about ApplicationService , it uses constructor injection with NInject. So, making fun of it with NInject.MockingKernel , will the dependency chain be established?

+4
source share
1 answer

In unit testing, there are few or no benefits when using dependency injection. Injection injection helps you create loose coupling components, and loose coupling components are easier to test, that is.

So, if you want to test some service, just create mock its dependencies and pass them to this service as usual (there is no need to include the IOC container here, I can hardly imagine that you will need some functions of IOC containers - such as context binding, interception and etc. - inside unit test).

If you want your ApplicationService to be easily tested, it should look more:

 public class ApplicationService: IApplicationService { private readonly IEntityFrameworkRepo repo; // dependency passed by constructor public ApplicationService(IEntityFrameworkRepo repo) { this.repo = repo; } // save to db when DTO is eligible public ApplicationDto Add(ApplicationDto dto) { // some business rule if(dto.Id > 0 && dto.Name.Contains(string.Empty)){ //add to dbcontext and commit }else{ throw new NotEligibleException(); } } } 

Here the dependency is passed by the constructor. In the application code, you will use it together with the IOC container to create an constructor injection (the IOC container will be responsible for instantiating IEntityFrameworkRepo ).

But in unit test, you can simply pass in an instance of some IEntityFrameworkRepo implementation created by yourself.

ApplicationDto

While ApplicationDto is some object that can be created manually, I can use it directly in unit-test (creating instances manually). Otherwise, I will have to wrap it with an interface like IApplicationDto in order to be able to make fun of it with Moq.

 public class ApplicationDto{ public int Id {get; set;} public string Name {get; set;} } 

Here is what the unit test would look like:

In the unit test, I will use the mocked implementation of IApplicationRepo , because I do not want to configure, for example. database connections, web services, etc., and my main intention is to test ApplicationService not the main repository. Another advantage is that the test will be run without a specific configuration for different machines. To create some kind of db repository I can use for example. List

 [Test(Description = "Test If can successfully add application")] public void CanAddApplicationIfEligible() { var repo = GetRepo(); var appService = new ApplicationService(repo); var testAppDto = new ApplicationDto() { Id = 155, Name = "My Name" }; var currentItems = repo.ApplicationDtos.Count(); appService.Add(testAppDto); Assert.AreEqual(currentItems + 1, repo.ApplicationDtos.Count()); var justAdded = repo.ApplicationsDto.Where(x=> x.Id = 155).FirstOrDefault(); Assert.IsNotNull(justAdded); ///.... } private static IEntityFrameworkRepo GetRepo{ // create a mock repository var listRepo = new List<ApplicationDto>{ new ApplicationDto {Id=1, Name="MyName"} }; var repo = new Mock<IEntityFrameworkRepo>(); // setup the methods you know you will need for testing // returns initialzed list instead of DB queryable like in real impl. repo.Setup(x => x.ApplicationDtos) .Returns<IQueryable<ApplicationDto>>(x=> listRepo); // adds an instance of ApplicationDto to list repo.Setup(x => x.Add(It.IsAny<ApplicationDto>()) .Callback<ApplicationDto>(a=> listRepo.Add(a)); return repo.Object; } 

Note:

The ninject.mockingkernel extension has been updated. The approach described in the wiki example can make your block test code bit tidier, but the approach described there is definitely not for injection (it's a service locator).

+6
source

All Articles