I have no experience on writting Unit Tests and I am starting with it.
My project has a Data Access Layer (with nhibernate) where I have repositories that are injected by an IoC container into some Services in a Business Layer. I want to write Unit Tests to test some methods on the Services (business Layer). I know it is important to have Moq
s to simulate the Repositories and avoid hits over the dataBase. I would like to know how to test this method:
public bool AddNewProject(ProjectViewModel viewModel)
{
// _projectRepository is an interface: IProjectRepository, resolved by IoC container
if (_projectRepository.ExistsNumber(viewModel.Number))
{
Validation.AddError("Number", GlobalResource.DuplicatedNumber);
return false;
}
if (_projectRepository.GetTotalAvailable(viewModel.ItemId) > 0)
{
Validation.AddError("ItemId", GlobalResource.NotItemAvailable);
return false;
}
var project = Mapper.Map<Project>(viewModel);
project.Data = _projectRepository.GetData(viewModel.ItemId);
_projectRepository.Save(project);
viewModel.Id = project.Id;
return true;
}
I know I have to write at least three unit tests, one for each validation and one for success. The problem is that in the AutoMapper
configuration, I have my IoC container resolving a type the AfterMap
event, for sample:
config.CreateMap<ProjectViewModel, Project>()
.AfterMap((vm, p) => {
// it is necessary because nhibernate will save this relation
var cityRepository = container.Resolve<ICityRepository>();
p.City = cityRepository.Load(vm.CityId);
});
I saw in some place on the web that it is not necessary to have the IoC container in the unit test and I should Moq
just the methods I need (not sure if it is correct). Should I have to define memory repositories and register them on a ioc container on the test project? I would be difficult to test because i need to rewrite all the repositories (more than 300).
Obs: It is difficult to change because there are more than 300 entities using Repository.Load
to make associations on the AfterMap
event on the AutoMapper
.
This is my unit test:
[TestMethod]
public void Should_not_save_a_project_by_existent_number()
{
var viewModel = new ProjectViewModel();
viewModel.Code = "PJT";
viewModel.CityId = 1;
viewModel.ItemId = 1;
viewModel.Name = "This is a test";
// for the validation, I use this simulator in memory (in asp.net mvc I encapsulate the ModelState)
var validator = new MemoryValidation();
var projectMoqRepository = new Mock<IProjectRepository>();
// I will mock methods here...
var projectService = new ProjectService(projectMoqRepository.Object, validator);
// the ICityRepository is defined on the IoC, so when I call AddNewProject
// it will be resolved inside the AutoMapper context on the AfterMap event.
// it is not injected on the ProjectService ctor.
var result = projectService.AddNewProject(viewModel);
projectService.Validation["Number"].ShouldNotBeEmpty();
result.ShouldBeFalse();
}