单元测试依赖于AutoMapper和类型转换器的ASP.NET MVC应用程序服务

时间:2011-08-08 22:04:16

标签: asp.net-mvc unit-testing ninject automapper

我的ASP.NET MVC 3应用程序的服务层使用AutoMapper将视图模型映射到业务对象。我实现了类型转换器,将post / get请求中提交的对象ID转换为业务对象.Type转换器通过ID查找数据库中的实体,并从中重建业务。例如:

class UserViewModel {
   // user fields
   Guid? Manager; // this is an ID of another user in the system
}

服务将调用AutoMapper:

var userModel = Mapper.Map<UserViewModel, UserModel>(viewModel);

映射到此类:

class UserModel {
    // other fields...
    UserModel Manager;
}

借助类型转换器,通过View GUID从视图模型中查找数据库中的另一个用户。使用Ninject为类型转换器注入依赖关系,一切都在Web应用程序中正常工作。

我正在尝试编写单元测试,它将使用带有类型转换器的模拟存储库。可以将AutoMapper配置为使用用户提供的功能构建服务:

Mapper.Initialize(cfg =>
{
    cfg.ConstructServicesUsing(type => Kernel.GetService(type));
});

在Web应用程序中,Kernel是Ninject,对于测试,我决定提供自己的方法,从字典中返回所请求类型的实例:

Dictionary<Type, object> typeDict = new Dictionary<Type, object>()
{
    { typeof(IRepository), new MockRepository() }
};

...
Mapper.Initialize(cfg =>
{
    cfg.ConstructServicesUsing(type => { return typeDict[type]; } );
});

这个想法是当AutoMapper配置为将Guid转换为这样的对象时:

Mapper.CreateMap<Guid?, TDropDown>()
       .ConvertUsing<GuidToSelectListValueConverter<TDropDown>>();

并且需要创建GuidToSelectListValueConverter的新实例并将其注入存储库,它将使用ConstructServicesUsing中配置的方法请求IRepository类型。

相反,AutoMapper实际上尝试获取GuidToSelectListValueConverter类型的实例。这意味着我负责创建类型转换器的新实例并为其注入依赖项。我的typeDict应该是这样的:

Dictionary<Type, object> typeDict = new Dictionary<Type, object>()
{
    { typeof(GuidToSelectListValueConverter), new GuidToSelectListValueConverter(
               new MockRepository()) }
};

我确实有很多类型转换器,并且手动编写解析器函数似乎不可行。这让我思考。在我的单元测试中简单地配置Ninject来解决这些依赖关系是不是错了?我可以将IRepository绑定到MockRepository,然后当我需要一个服务实例时,只需调用Kernel.GetService(typeof(MyService))并让Ninject用MockRepository注入它。额外的好处是AutoMapper还将使用Ninject来获取类型转换器和值解析器的实例:

// configure Ninject
Kernel.Bind<IRepository>().To<MockRepository>();
// initialize AutoMapper
Mapper.Initialize(cfg => 
{ 
    cfg.ConstructServicesUsing(t => Kernel.GetService(t)); 
});
// create an instance of service to test
var service = Kernel.GetService(IMyService);
// do work
var result = service.DoWork();
// analyze result

现在,当DoWork方法调用Mapper.Map类型转换器时,使用Ninject创建。

欢迎任何建议,想法和最佳实践建议。

谢谢!

1 个答案:

答案 0 :(得分:1)

查看this post on using IoC with AutoMapper

这有助于我在控制器中使用IMappingEngine代替Mapper,朝着正确的方向前进。