Eth*_*fer 3 c# asp.net-mvc unit-testing automapper
我无法让automapper在我的单元测试中工作.我正在注入映射引擎,这在代码中工作正常,但不在测试中.这是我的测试设置和测试.我正在使用Moq来模拟映射引擎.
private static IDbContext Context { get; set; }
private static Mock<IMappingEngine> Mapper { get; set; }
private static Guid MenuId { get; set; }
private static Guid menuItem1Id { get; set; }
private static Guid menuItem2Id { get; set; }
private static Guid menuItem3Id { get; set; }
[ClassInitialize]
public static void SetUp(TestContext context)
{
MenuId = Guid.NewGuid();
Context = new TestDbContext();
menuItem1Id = Guid.NewGuid();
menuItem2Id = Guid.NewGuid();
menuItem3Id = Guid.NewGuid();
var contentPage1 = new ContentPage { Id = Guid.NewGuid(), ActionName = "ActionName1", ControllerName = "ControllerName1", MenuItemId = menuItem1Id };
var contentPage2 = new ContentPage { Id = Guid.NewGuid(), ActionName = "ActionName2", ControllerName = "ControllerName2", MenuItemId = menuItem2Id };
var contentPage3 = new ContentPage { Id = Guid.NewGuid(), ActionName = "ActionName3", ControllerName = "ControllerName3", MenuItemId = menuItem3Id };
var menuItem1 = new MenuItem { Id = menuItem1Id, MenuId = MenuId, DisplayName = "MenuItem1", ExternalUrl = null, Target = Target._self, Active = true, ContentPage = contentPage1 };
var menuItem2 = new MenuItem { Id = menuItem1Id, MenuId = MenuId, DisplayName = "MenuItem2", ExternalUrl = null, Target = Target._self, Active = true, ContentPage = contentPage2 };
var menuItem3 = new MenuItem { Id = menuItem1Id, MenuId = MenuId, DisplayName = "MenuItem3", ExternalUrl = null, Target = Target._self, Active = true, ContentPage = contentPage3 };
var menu = new Models.Menu { Id = MenuId, Name = "TestMenu", SiteId = Guid.NewGuid(), MenuItems = new List<MenuItem> { menuItem1, menuItem2, menuItem3 } };
Context.Menus.Add(menu);
Context.MenuItems.Add(menuItem1);
Context.MenuItems.Add(menuItem2);
Context.MenuItems.Add(menuItem3);
var menuItemQueryResult = new List<MenuItemQueryResult>
{
new MenuItemQueryResult { Id = menuItem1Id, DisplayName = "MenuItem1", ExternalUrl = null, Target = Target._self, Active = true, ActionName = "ActionName1", ControllerName = "ControllerName1" },
new MenuItemQueryResult { Id = menuItem1Id, DisplayName = "MenuItem2", ExternalUrl = null, Target = Target._self, Active = true, ActionName = "ActionName2", ControllerName = "ControllerName2" },
new MenuItemQueryResult { Id = menuItem1Id, DisplayName = "MenuItem3", ExternalUrl = null, Target = Target._self, Active = true, ActionName = "ActionName3", ControllerName = "ControllerName3" }
};
Mapper = new Mock<IMappingEngine>();
Mapper.Setup(m => m.Map<IEnumerable<MenuItem>, IEnumerable<MenuItemQueryResult>>(It.IsAny<IEnumerable<MenuItem>>()))
.Returns(menuItemQueryResult);
}
[TestMethod]
public void Retrieve_RequestMenu_QueryResultReturned()
{
var handler = new MenuQueryHandler(Context, Mapper.Object);
var query = new MenuQuery("TestMenu");
var result = handler.Retrieve(query);
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(MenuQueryResult));
var item = result.FirstOrDefault(r => r.Id == menuItem1Id);
Assert.IsNotNull(item);
}
Run Code Online (Sandbox Code Playgroud)
以下是我正在测试的内容:
public class MenuQueryHandler : IQueryHandler<MenuQuery, MenuQueryResult>
{
private IDbContext Context { get; set; }
private IMappingEngine Mapper { get; set; }
public MenuQueryHandler(IDbContext context, IMappingEngine mapper)
{
Context = context;
Mapper = mapper;
}
public MenuQueryResult Retrieve(MenuQuery query)
{
Ensure.Argument.Is(query != null);
Ensure.Argument.IsNot(query.MenuName == string.Empty);
// Create the view model query result
var result = new List<MenuItemQueryResult>();
// Pull the required item from the cont.ext
var menuItems = Context.MenuItems.Include(m => m.ContentPage).ToList();
Mapper.Map(menuItems, result);
return new MenuQueryResult(result);
}
}
Run Code Online (Sandbox Code Playgroud)
测试运行,但映射永远不会发生.
有几个问题:
你并没有嘲笑你实际调用的方法.您正在测试的方法调用此方法:
TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
Run Code Online (Sandbox Code Playgroud)
这种重载Map采用现有destination对象并映射到其中.
在你的测试中,你是在模拟重载Map,返回一个新的实例TDestination:
TDestination Map<TSource, TDestination(TSource source);
Run Code Online (Sandbox Code Playgroud)
请注意,您正在模拟的那个接受一个参数,而您实际调用的那个参数需要两个参数.
您的Setup方法在IEnumerable<MenuItem>和之间设置伪映射IEnumerable<MenuItemQueryResult>.在你的测试中,你实际上是Map用a List<MenuItem>和a 调用List<MenuItemQueryResult>.
在实际使用中,AutoMapper将要处理的List,以List映射您使用的IEnumerable映射.但是,使用模拟方法,您实际上并没有使用您指定的确切类型参数调用该方法.因此,您必须更改Setup呼叫并更改虚假映射.
因此,要解决这些问题,您可以执行以下两项操作之一:
更改方法以使用Map返回新实例的重载.
看起来你不需要使用带有两个参数的重载,所以你可以调整方法:
var result = Mapper.Map<List<MenuItemQueryResult>(menuItems);
Run Code Online (Sandbox Code Playgroud)
然后在你的测试中:
Mapper.Setup(m => m.Map<List<MenuItem>, List<MenuItemQueryResult>>(It.IsAny<List<MenuItem>>())
Mapper
.Setup(m => m.Map<List<MenuItem>, List<MenuItemQueryResult>>(It.IsAny<List<MenuItem>>()))
.Returns(menuItemQueryResult);
Run Code Online (Sandbox Code Playgroud)更改测试以模拟正确的重载Map.
这有点不太直观,但可能.您必须提供该Map方法的虚假实现:
Mapper
.Setup(m => m.Map<List<MenuItem>, List<MenuItemQueryResult>>(It.IsAny<List<MenuItem>>(), It.IsAny<List<MenuItem>>()))
.Callback((List<MenuItem> menuItems, List<MenuItemQueryResult> queryResults) =>
{
queryResults.AddRange(menuItemQueryResult);
});
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
12327 次 |
| 最近记录: |