2014-08-29 46 views
8

我在我的應用中的典型庫模式設置有DbContext(EF6):EF6 DbSet <T>返回null在起訂量

public class MyDbContext : EFContext<MyDbContext> { 

    public MyDbContext() { } 

    public virtual DbSet<CartItem> Cart { get; set; } 

和庫:

public class GenericEFRepository<TEntity, TContext> 
    where TEntity : class, new() 
    where TContext : EFContext<TContext> { 

    private readonly TContext _context; 

    public GenericEFRepository(TContext context) { 
     _context = context; 
    } 
    //... 
    public virtual TEntity Insert(TEntity item) { 
     return _context.Set<TEntity>().Add(item); 
    } 

我測試這個與Moq 4.2(通過this tutorial)創建模擬上下文:

 // Arrange 
     var mockSet = new Mock<DbSet<CartItem>>(); 

     var mockContext = new Mock<MyDbContext>(); 
     mockContext.Setup(c => c.Cart).Returns(mockSet.Object); 

     // Act 
     var service = new GenericEFRepository<CartItem, MyDbContext>(mockContext.Object); 
     service.Insert(new CartItem() { 
      Id = 1, 
      Date = DateTime.Now, 
      UserId = 1, 
      Detail = string.Empty 
     }); 

     // Assert 
     mockSet.Verify(s => s.Add(It.IsAny<CartItem>()), Times.Once()); 

的問題是,當我到達這條線:

return _context.Set<TEntity>().Add(item); 

_context.Set<TEntity>()返回null。在使用一些Google搜索之後,似乎在EF5中有必要返回IDbSet<T>用於模擬該集合,但不包含EF6。這是不是這種情況,或者我錯過了什麼?

+1

我是否錯過了設置'Set ()'方法返回'mockSet'的地方? – 2014-08-29 13:34:42

+0

你必須澄清這一點。根據我鏈接到的教程,唯一處理的是var mockSet = new Mock >();''和'mockContext.Setup(c => c.Cart).Returns(mockSet.Object );'。 – 2014-08-29 13:36:04

+3

的確如此,但是在教程的服務代碼(快速瀏覽之後)中沒有看到他們調用'Set ()',而您的代碼卻是這樣。添加一個設置,我認爲它會工作。 – 2014-08-29 13:38:05

回答

15

添加一個設置爲Set<T>()方法:

mockContext.Setup(c => c.Set<CartItem>()).Returns(mockSet.Object); 

即使對實體EFContext財產CartSet<CartItem>()指向同一個對象,上下文的模擬不知道這一點,所以你需要明確告訴它要返回什麼。

由於這是一個鬆散的模擬,對未設置的方法的調用返回默認值,在本例中爲null。嚴格的嘲笑是很好的幫助找到這個錯誤,但也have maintenance costs that other folks don't want to deal with

+0

也可能需要模擬DbSet上的其他功能。 – Jess 2015-06-03 20:36:33