问题
I have a mapping:
var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Foo, FooDto>()
        .ForMember(dest => dest.Id,
            opt => opt.MapFrom(src => src.Id))
        .ForMember(dest => dest.Name,
            opt => opt.MapFrom(src => src.Name))
        .ForMember(dest => dest.PhoneNumber,
            opt => opt.MapFrom(src => src.PhoneNumbers.Number)) //etc.
});
and I'm trying to use it in a unit test calling into some mocked up EF objects:
var ids = new List<string>()
    {
        "123";
        "456";
        "789";
    };
var data = new List<Foo>();
foreach(var id in ids)
{
    data.Add(new Foo() { Id = id });
}
this.mockContext = new Mock<entities>();
this.mockSet = new Mock<DbSet<Foo>>();
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.Provider).Returns(data.Provider);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.Expression).Returns(data.Expression);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.ElementType).Returns(data.ElementType);
this.mockSet.As<IQueryable<Foo>>().Setup(p => p.GetEnumerator()).Returns(data.GetEnumerator());
When I query the entities directly:
var id = "123";
var bar = this.mockContext.Object.Foo.Where(p => p.id == id);
I get back an IQueryable() with a single result, as expected. But when I try to project my object into a DTO:
var id = "123";
var buzz = this.mockContext.Object.Foo.Where(p => p.id == id).ProjectTo<FooDto>(this.config);
The IQueryable I get back throws a Null Reference Exception if I try to access the results in any way. So for example:
buzz.ToList();
buzz.SingleOrDefault(); // This mirrors the actual call in my code since this is a GetById query.
both fail. What am I missing here?
回答1:
The problem lies is that Foo uses EF navigation properties to refer to other objects. Specifically a PhoneNumber in this instance. Since the test data is created without the linked PhoneNumber object, it breaks inside of the ProjectTo method. This isn't a problem when grabbing the top level Queryable directly, but Automapper needs the objects to exist (even if they're empty) in order to complete the mapping. Changing that line to:
data.Add(new Foo() { Id = id, PhoneNumber = new PhoneNumber() });
allows the ProjectTo method to complete, albeit with null values.
来源:https://stackoverflow.com/questions/43240089/why-is-automapper-projectto-throwing-a-null-reference-exception