如何使用Moq和AutoMapper测试此代码

时间:2016-12-28 12:26:11

标签: c# unit-testing nhibernate automapper moq

我没有编写单元测试的经验,我开始使用它。 我的项目有一个数据访问层(带有nhibernate),我有一些存储库,由IoC容器注入到业务层的某些服务中。我想编写单元测试来测试服务(业务层)上的一些方法。我知道让Moq来模拟存储库并避免命中数据库很重要。我想知道如何测试这种方法:

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

我知道我必须编写至少三个单元测试,一个用于每个验证,一个用于成功。问题是在AutoMapper配置中,我的IoC容器解析了AfterMap事件的类型,样本:

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

我在网上的某个地方看到没有必要在单元测试中使用IoC容器,我应该Moq只需要我需要的方法(不确定它是否正确)。我是否必须定义内存存储库并在测试项目的ioc容器上注册它们?我很难测试,因为我需要重写所有的存储库(超过300个)。

Obs:很难改变,因为有超过300个实体使用Repository.Load来对AfterMap上的AutoMapper事件进行关联。

这是我的单元测试:

[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(); 
}

0 个答案:

没有答案