2017-04-05 60 views
0

我有一个映射:为什么Automapper.ProjectTo()会引发空引用异常?

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

,我想在一个单元测试调入一些嘲笑了EF对象来使用它:

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

当我直接查询实体:

var id = "123"; 
var bar = this.mockContext.Object.Foo.Where(p => p.id == id); 

如预期的那样,我得到一个带有单个结果的IQueryable()。但是,当我尝试我的投射对象到DTO:

var id = "123"; 
var buzz = this.mockContext.Object.Foo.Where(p => p.id == id).ProjectTo<FooDto>(this.config); 

的IQueryable的,我回去会抛出一个空引用异常,如果我尝试访问任何方式的结果。例如:

buzz.ToList(); 
buzz.SingleOrDefault(); // This mirrors the actual call in my code since this is a GetById query. 

都失败。我在这里错过了什么?

回答

0

问题在于Foo使用EF导航属性来引用其他对象。在这种情况下具体为PhoneNumber。由于测试数据是在没有链接的对象的情况下创建的,因此它会在ProjectTo方法中断开。当直接获取顶级Queryable时,这并不是一个问题,但Automapper需要对象存在(即使它们为空)以完成映射。更改该行:

data.Add(new Foo() { Id = id, PhoneNumber = new PhoneNumber() }); 

允许ProjectTo方法来完成,尽管空值。

相关问题