【发布时间】:2014-01-30 12:20:07
【问题描述】:
我是嘲笑新手。我想模拟我的基础存储库,它依赖于 Entity Framework 6 DbContext 但我失败了。我在谷歌搜索了很多,但没有得到任何足够的结果。最后我在testing with async queries 找到了一个例子并尝试遵循,但它对我有用。
这是我的代码:
数据库上下文:
public class TimeSketchContext : DbContext
{
public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}
基础存储库:
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);
}
}
测试:
[Fact]
public async Task DbTest()
{
var dummyData = GetEmployeeSkills();
var mockSet = new Mock<DbSet<EmployeeSkill>>();
mockSet.As<IDbAsyncEnumerable<EmployeeSkill>>()
.Setup(x => x.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<EmployeeSkill>(dummyData.GetEnumerator()));
mockSet.As<IQueryable<EmployeeSkill>>()
.Setup(x => x.Provider)
.Returns(new TestDbAsyncQueryProvider<EmployeeSkill>(dummyData.Provider));
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.Expression).Returns(dummyData.Expression);
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.ElementType).Returns(dummyData.ElementType);
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.GetEnumerator()).Returns(dummyData.GetEnumerator());
var mockContext = new Mock<TimeSketchContext>();
mockContext.Setup(c => c.EmployeeSkill).Returns(mockSet.Object);
var baseRepository = new BaseRepository<EmployeeSkill>(mockContext.Object);
var data = await baseRepository.FindAsync(1);
Assert.NotEqual(null, data);
}
private EmployeeSkill GetEmployeeSkill()
{
return new EmployeeSkill
{
SkillDescription = "SkillDescription",
SkillName = "SkillName",
Id = 1
};
}
private IQueryable<EmployeeSkill> GetEmployeeSkills()
{
return new List<EmployeeSkill>
{
GetEmployeeSkill(),
GetEmployeeSkill(),
GetEmployeeSkill(),
}.AsQueryable();
}
结果是:
Assert.NotEqual() 失败
我认为问题是
public BaseRepository(DbContext innerDbContext)
{
InnerDbContext = innerDbContext;
InnerDbSet = InnerDbContext.Set<T>(); <<<<<<<<<<<
}
但不明白为什么以及如何解决这个问题。
我正在使用:
- Visual Studio 2013 Ultimate
- 起订量
- xUnit
提前致谢。
【问题讨论】:
-
对于未来的读者:如果您在各处注入 DbContext 并且您无法将其抽象为存储库/接口,并且您绝对需要“模拟”它,因为它是非虚拟的,您可以使用 Microsoft Fakes Assemblies 来实现这一点,因为它会做一些花哨的 IL 东西,让您为对象上的非虚拟方法提供替代实现。
-
我强烈建议查看“Effort”(effort.codeplex.com),这是一个 EF 单元测试工具,它可以在内存中创建一个足够真实的 EF 数据库来进行测试。我们在模拟 EF 方面也遇到了很多麻烦,但归根结底,测试 EF 模拟是一场从苹果到橘子的惨败。 (例如,模拟测试使用 L2O 而不是 L2E。)
-
它看起来是个不错的工具,稍后会检查。无论如何感谢@RJB
-
对于 EF 6,我发现本文中的代码非常有用:msdn.microsoft.com/en-us/library/dn314429.aspx 我也遇到了模拟 AsNoTracking() 的问题,这个出色的答案解决了这个问题:stackoverflow.com/a/27087604/3507333
-
该努力的 url 出现了一个谷歌警告,警告未来的危险程序,并建议不要继续。
标签: c# .net entity-framework unit-testing moq