2017-04-05 102 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方法來完成,儘管空值。

相關問題