C# 单元测试自动映射器

C# 单元测试自动映射器,c#,asp.net-mvc,unit-testing,automapper,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 Gu

我很难让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);
}
private静态IDbContext上下文{get;set;}
私有静态模拟映射程序{get;set;}
私有静态Guid MenuId{get;set;}
私有静态Guid menuItem1Id{get;set;}
私有静态Guid menuItem2Id{get;set;}
私有静态Guid menuItem3Id{get;set;}
[分类初始化]
公共静态无效设置(TestContext上下文)
{
MenuId=Guid.NewGuid();
Context=newtestdbcontext();
menuItem1Id=Guid.NewGuid();
menuItem2Id=Guid.NewGuid();
menuItem3Id=Guid.NewGuid();
var contentPage1=newcontentpage{Id=Guid.NewGuid(),ActionName=“ActionName1”,ControllerName=“ControllerName1”,MenuItemId=menuItem1Id};
var contentPage2=newcontentpage{Id=Guid.NewGuid(),ActionName=“ActionName2”,ControllerName=“ControllerName2”,MenuItemId=menuItem2Id};
var contentPage3=newcontentpage{Id=Guid.NewGuid(),ActionName=“ActionName3”,ControllerName=“ControllerName3”,MenuItemId=menuItem3Id};
var menuItem1=new MenuItem{Id=menuItem1Id,MenuId=MenuId,DisplayName=“menuItem1”,ExternalUrl=null,Target=Target.\u self,Active=true,ContentPage=contentPage1};
var menuItem2=new MenuItem{Id=menuItem1Id,MenuId=MenuId,DisplayName=“menuItem2”,ExternalUrl=null,Target=Target.\u self,Active=true,ContentPage=contentPage2};
var menuItem3=new MenuItem{Id=menuItem1Id,MenuId=MenuId,DisplayName=“menuItem3”,ExternalUrl=null,Target=Target.\u self,Active=true,ContentPage=contentPage3};
var menu=new Models.menu{Id=MenuId,Name=“TestMenu”,SiteId=Guid.NewGuid(),MenuItems=new List{menuItem1,menuItem2,menuItem3};
Context.Menus.Add(菜单);
Context.MenuItems.Add(menuItem1);
Context.MenuItems.Add(menuItem2);
Context.MenuItems.Add(menuItem3);
var menuItemQueryResult=新列表
{
新建MenuItemQueryResult{Id=menuItem1Id,DisplayName=“MenuItem1”,ExternalUrl=null,Target=Target.\u self,Active=true,ActionName=“ActionName1”,ControllerName=“ControllerName1”},
新建MenuItemQueryResult{Id=menuItem1Id,DisplayName=“MenuItem2”,ExternalUrl=null,Target=Target.\u self,Active=true,ActionName=“ActionName2”,ControllerName=“ControllerName2”},
新建MenuItemQueryResult{Id=menuItem1Id,DisplayName=“MenuItem3”,ExternalUrl=null,Target=Target.\u self,Active=true,ActionName=“ActionName3”,ControllerName=“ControllerName3”}
};
Mapper=newmock();
Setup(m=>m.Map(It.IsAny())
.返回(menuItemQueryResult);
}
[测试方法]
public void Retrieve_RequestMenu_QueryResultReturned()
{
var handler=new MenuQueryHandler(上下文,Mapper.Object);
var query=新菜单查询(“测试菜单”);
var result=handler.Retrieve(查询);
Assert.IsNotNull(结果);
IsInstanceOfType(结果,类型(MenuQueryResult));
var item=result.FirstOrDefault(r=>r.Id==menuItem1Id);
Assert.IsNotNull(项);
}
以下是我正在测试的内容:

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

    }
}
公共类MenuQueryHandler:IQueryHandler
{
私有IDbContext上下文{get;set;}
私有IMappingEngine映射程序{get;set;}
公共菜单查询句柄(IDbContext上下文,IMappingEngine映射器)
{
上下文=上下文;
映射器=映射器;
}
公共MenuQueryResult检索(MenuQuery查询)
{
确保.Argument.Is(查询!=null);
确保.Argument.IsNot(query.MenuName==string.Empty);
//创建视图模型查询结果
var result=新列表();
//从cont.ext中拉出所需的项目
var menuItems=Context.menuItems.Include(m=>m.ContentPage.ToList();
Mapper.Map(菜单项、结果);
返回新的MenuQueryResult(结果);
}
}

测试将运行,但映射从未发生。

您的模拟映射器设置为返回menuItemQueryResult,但在您的实现中,您不获取mapper.Map函数的结果。在我看来,你应该像这样使用你的制图器:

result = Mapper.Map(menuItems);
编辑:

如果您使用的是Automapper,并且针对以下类型正确配置了Automapper:

result = Mapper.Map<IEnumerable<MenuItem>, List<MenuItemQueryResult>>(menuItems);
result=Mapper.Map(menuItems);

有几个问题:

  • 您并不是在嘲笑实际调用的方法。您正在测试的方法调用此方法:

    TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
    
    请注意,您正在模拟的一个接受一个参数,而您实际调用的一个接受两个参数

  • 您的
    Setup
    方法在
    IEnumerable
    IEnumerable
    之间设置了一个伪映射。在您的测试中,您实际上是使用
    列表和
    列表调用
    Map

    在实际使用中,AutoMapper将为您使用
    IEnumerable
    映射处理
    List
    List
    的映射。但是,对于模拟方法,实际上并不是使用指定的确切类型参数调用该方法。因此,您必须更改
    设置
    调用并更改假映射

  • 因此,要解决这些问题,您可以做以下两件事之一:

  • 更改方法以使用返回新实例的
    Map
    重载

    看起来不需要使用包含两个参数的重载,因此可以调整方法:

    var result = Mapper.Map<List<MenuItemQueryResult>(menuItems);
    

  • 这甚至不需要编译。我假设您自己编写了映射程序,在这种情况下,请更改实现。如果您使用的是AutoMapper,那么它应该是:result=Mapper.Map(menuItems);或者检查您使用的映射器的详细信息。这在测试中返回null,但在实际站点上有效,这使我认为问题在于我的Moq设置非常好。正是我需要的。1)
    var result = Mapper.Map<List<MenuItemQueryResult>(menuItems);
    
    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);
    
    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);
        });