Unit-Tests automapper
Ich bin mit Mühe automapper für die Arbeit in meinem unit-test. Ich bin die Injektion der mapping-engine, und dies funktioniert problemlos, im code, aber nicht im test. hier ist mein test-set-up und testen. Ich bin mit Moq, zu verspotten die mapping-engine.
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);
}
Und hier ist, was ich Teste:
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);
}
}
Der test läuft, aber die Zuordnung tritt nie ein.
- Verspotten Sie nicht AutoMapper. Ich habe nie, nie tun.
- Sind Sie mit der aktuellen Instanz von automapper in tests? Was ich versucht habe zu erreichen, war die Injektion der automapper Motor (IMappingEngine). Wenn ich es injizieren, muss ich eine Instanz für die Prüfung. Sie sagen nicht injizieren IMappingEngine?
- Yep. Auch wenn Sie Spritzen den IMappingEngine, ich weiß nicht verspotten es. Ich benutze die Reale Sache.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es ein paar Probleme:
Sie sind nicht lustig die Methode, die Sie tatsächlich anrufen. Die Methode, die Sie testen diese Methode aufruft:
Diese überladung von
Map
dauert ein vorhandenesdestination
Objekt und Karten hinein.In deinem test, du bist der Spott der überlastung der
Map
gibt eine neue InstanzTDestination
:Beachten Sie, dass Sie bei Spott nimmt einen parameter und die, die Sie eigentlich aufrufen nimmt zwei.
Ihre
Setup
- Methode legt eine falsche Zuordnung zwischenIEnumerable<MenuItem>
undIEnumerable<MenuItemQueryResult>
. In Ihrem test, bist du eigentlich aufrufenMap
mit einemList<MenuItem>
und einList<MenuItemQueryResult>
.In der tatsächlichen Nutzung, AutoMapper ist behandeln die
List
zuList
mapping für die Verwendung derIEnumerable
mapping. Mit einem verspottet Methode obwohl, bist du nicht eigentlich Aufruf der Methode mit der genaue Typ-Parameter, die Sie angegeben. So müssen Sie zum ändern derSetup
aufrufen und ändern die fake-mapping.So zu bekommen, um diese Probleme können Sie eines von zwei Dingen tun:
Ändern Sie die Methode, um die überlastung der
Map
gibt eine neue Instanz.Sieht es nicht aus, müssen Sie mit der überladung, die zwei Parameter nimmt, so können Sie zwicken die Methode:
Und dann im test:
Ändern der test zum simulieren der richtige überlastung der
Map
.Dies ist etwas weniger intuitiv, aber möglich. Sie haben, um eine gefälschte Umsetzung der
Map
Methode:Ihre mock-mapper ist so eingerichtet, dass zurück menuItemQueryResult aber in Ihnen Umsetzung Sie nicht nehmen, das Ergebnis der Mapper.Map-Funktion. Meiner Meinung nach sollten Sie Ihre mapper wie diese:
Edit:
Falls Sie mit Automapper und es ist korrekt konfiguriert für die Typen: