Reputation:
I have a model in Entity Framework. I want to make sure that Application Service is reading the Generic Repository pointing to the database correctly. How would I test this in Xunit, I am kind of stuck ? Receiving the error below, maybe I need to rewrite code. Need to validate that App service can read example data row below in InMemorydatabase.
Model:
public partial class Department
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
.... plus additional
}
DTO:
public class DepartmentDto
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
}
Base Repository from IRepository:
public async Task<T> GetAsync(int id)
{
return await Table.FindAsync(id);
}
**Constructor:**
public BaseRepository(DbContext context)
{
_context = context;
Table = _context.Set<T>();
}
Service: DepartmentAppService.cs
public async Task<DepartmentDto> GetDepartmentById(int id)
{
var department = await departmentRepository.GetAsync(id);
var departmentDto = mapper.Map<Department, DepartmentDto>(department);
return departmentDto;
}
**Constructor:**
public DepartmentAppService(IRepository<Department> departmentRepository, IMapper mapper)
{
this.departmentRepository = departmentRepository;
this.mapper = mapper;
}
Attempted Test Code:
public async Task Get_DepartmentById_Are_Equal()
{
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options);
Mock<IRepository<Department>> departmentRepositoryMock = new Mock<IRepository<Department>>();
Mock<IMapper> mapperMock = new Mock<IMapper>();
Mock<DepartmentAppService> departmentAppServiceMock = new Mock<DepartmentAppService>(departmentRepositoryMock, mapperMock);
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
var test = await departmentAppServiceMock.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
Receiving Error: How to Fix?
'Mock<DepartmentAppService>' does not contain a definition for 'GetDepartmentById' and no accessible extension method 'GetDepartmentById' accepting a first argument of type 'Mock<DepartmentAppService>' could be found (are you missing a using directive or an assembly reference?)
Also have dependency injection in the program. Open to code being rewritten as required,
Upvotes: 5
Views: 7794
Reputation: 4041
You don't want to create a mock of the DepartmentAppService
. You want to create an instance. The method you are testing requires an instance of the real object, not a mock. You want to test the actual object's code, mocks don't run any code but only return fake data.
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(sharedServicesProfile);
});
mapper = config.CreateMapper();
var departmentAppService = new DepartmentAppService(departmentRepositoryMock.Object, mapperMock.Object);
If you are using an InMemory database and you are actually getting the data for your repository from that InMemory database, you don't want to Mock your repository either as you are hitting a physical database and returning real data and not mocked data.
To be honest, I think you need to read up a bit more on testing and mocking. Looks like there are a few core concepts missing... This is one way to write what you are trying to do.
AutoMapper.Mapper.Initialize(m => m.AddProfile<YOUR AUTOMAPPER PROFILE>());
AutoMapper.Mapper.AssertConfigurationIsValid();
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options))
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
context.SaveChanges();
var departmentRepository = new Repository<Department>>(context);
var departmentAppService = new DepartmentAppService(departmentRepository, mapper);
var test = await departmentAppService.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
You may also want to think about disposing your context or wrapping it in a using. If the code doesn't run correctly if you copy paste there may be a few tweaks you need to make but it should be fairly close.
As you can see from the code above you still need to learn when to mock and when not to mock! No mocks were needed. You are also doing an integration test, if you didn't want an integration test you could remove the context stuff and mock the Repository and setup the mock to return the department.
Upvotes: 4