EF6 DbSet <T>在Moq中返回null

Ste*_*ins 8 c# unit-testing entity-framework moq entity-framework-6

我在我的应用程序中使用DbContext(EF6)设置了典型的存储库模式:

public class MyDbContext : EFContext<MyDbContext> {

    public MyDbContext () { }

    public virtual DbSet<CartItem> Cart { get; set; }
Run Code Online (Sandbox Code Playgroud)

和一个存储库:

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);
    }
Run Code Online (Sandbox Code Playgroud)

我正在使用Moq 4.2(遵循本教程)通过创建模拟上下文来测试它:

        // 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());
Run Code Online (Sandbox Code Playgroud)

问题是当我到达这一行时:

return _context.Set<TEntity>().Add(item);
Run Code Online (Sandbox Code Playgroud)

_context.Set<TEntity>()返回null.经过一些谷歌搜索似乎在EF5中,有必要返回IDbSet<T>Moq来模拟集合,但不是EF6.是不是这样,或者我错过了什么?

Pat*_*irk 16

添加Set<T>()方法的设置:

mockContext.Setup(c => c.Set<CartItem>()).Returns(mockSet.Object);
Run Code Online (Sandbox Code Playgroud)

即使在真实EFContext的属性CartSet<CartItem>()引用相同的对象,上下文的模拟不知道,所以你需要明确告诉它返回什么.

由于它是一个松散的模拟,因此对尚未设置的方法的调用将返回默认值,在本例中为null.严格的模拟很有助于发现此错误,但也有其他人不想处理的维护成本.