如何使用JustMock模拟EF 6异步方法?

时间:2014-01-11 20:33:43

标签: c# .net entity-framework asynchronous moq

我正在尝试使用JustMock模拟实体框架6.0.2异步方法。我关注testing with async queries但它是使用Moq编写的我试图在Mock Multiple Interfaces的帮助下将其转换为JustMock但是获得例外:

  

源IQueryable的提供程序未实现   IDbAsyncQueryProvider。只有实施的提供商   IDbAsyncQueryProvider可用于Entity Framework异步   操作。有关详细信息,请参阅   http://go.microsoft.com/fwlink/?LinkId=287068

这是我的代码:

var dummyData = GetEmployeeSkills();
var mockSet = Mock.Create<DbSet<EmployeeSkill>>();
(mockSet as IDbAsyncEnumerable<EmployeeSkill>).Arrange(x => x.GetAsyncEnumerator())
         .Returns(new TestDbAsyncEnumerator<EmployeeSkill>(dummyData.GetEnumerator()));

(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.Provider).Returns(new TestDbAsyncQueryProvider<EmployeeSkill>(dummyData.Provider));

(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.Expression).Returns(dummyData.Expression);
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.ElementType).Returns(dummyData.ElementType);
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.GetEnumerator()).Returns(dummyData.GetEnumerator());

var mockContext = Mock.Create<TimeSketchContext>();
mockContext.Arrange(x => x.Set<EmployeeSkill>()).Returns(mockSet);

baseRepository = new BaseRepository<EmployeeSkill>(mockContext);

private EmployeeSkill GetEmployeeSkill()
    {
        return new EmployeeSkill
        {
            SkillDescription = "SkillDescription",
            SkillName = "SkillName",
            Id = 1
        };
    }

    private IQueryable<EmployeeSkill> GetEmployeeSkills()
    {
        return new List<EmployeeSkill>
        {
            GetEmployeeSkill(),
            GetEmployeeSkill(),
            GetEmployeeSkill(),
        }.AsQueryable();
    }

测试:

[Fact]
public async Task DbTest()
{
   var data = await baseRepository.FindAsync(1);
   Assert.NotEqual(null, data);
}

存储库:

public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
    protected readonly DbContext InnerDbContext;
    protected DbSet<T> InnerDbSet;

    public BaseRepository(IDbContext innerDbContext)
    {
        InnerDbContext = innerDbContext as DbContext;
        InnerDbSet = innerDbContext.Set<T>();
    }

    public virtual Task<T> FindAsync(long id)
    {
        return InnerDbSet.FirstOrDefaultAsync(x=>x.Id == id);
    }
 }

界面:

public interface IDbContext
{
    DbSet<T> Set<T>() where T : class;
}

背景:

public class TimeSketchContext : DbContext, IDbContext
{
    public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}

1 个答案:

答案 0 :(得分:2)

因为JustMock可以在你写

时模拟非虚方法
var mockContext = Mock.Create<TimeSketchContext>();
mockContext.Arrange(x => x.Set<EmployeeSkill>()).Returns(mockSet);

它会模仿DbContext.Set<>而非IDbContext.Set<>,因此您会获得例外。

至少有两个解决方案:

  • 模拟您的IDbContext界面

    var mockContext = Mock.Create<IDbContext>();
    
  • 或者将您的BaseRepository更改为使用DbContext代替您的界面:

    public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
    {
        protected readonly DbContext InnerDbContext;
        protected DbSet<T> InnerDbSet;
    
        public BaseRepository(DbContext innerDbContext)
        {
            InnerDbContext = innerDbContext;
            InnerDbSet = InnerDbContext.Set<T>();
        }
    
        public virtual Task<T> FindAsync(long id)
        {
            return InnerDbSet.FirstOrDefaultAsync(x => x.Id == id);
        }
    }