繁体   English   中英

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

[英]Unit testing ASP.NET MVC application services that rely on AutoMapper and type converters

我的ASP.NET MVC 3应用程序的服务层使用AutoMapper将视图模型映射到业务对象。 我实现了类型转换器,将发布/获取请求中提交的对象ID转换为业务对象。类型转换器通过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;
}

借助类型转换器的帮助,该类型转换器通过Manager GUID从视图模型中查找数据库中的另一个用户。 使用Ninject向类型转换器注入依赖项,并且在Web应用程序中一切正常。

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

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

在Web应用程序中,内核是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创建类型转换器。

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

谢谢!

查看有关将IoC与AutoMapper结合使用的信息

通过在控制器中使用IMappingEngine而不是Mapper ,这有助于我朝正确的方向前进。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM