我试图在服务中的查询中测试业务逻辑。所以我不希望我的测试能够真正访问数据库,因为它们是单元测试,而不是集成测试。使用实体框架而不依赖注入的测试服务
所以我已经做了一个简单的例子,我的上下文,以及我如何试图填补它。
我有一个实体
public class SomeEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
和服务
public class Service
{
public int CountSomeEntites()
{
using (var ctx = new Realcontext())
{
int result = ctx.SomeEntities.Count();
return result;
}
}
}
而这才是真正的背景下
public partial class Realcontext : DbContext
{
public virtual DbSet<SomeEntity> SomeEntities { get; set; }
public Realcontext() : base("name=Realcontext")
{
InitializeContext();
}
partial void InitializeContext();
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}
所以我试图创建一个假背景和我在我的测试方法中虚构了真实环境的构造函数
这是假的情况下
public class FakeContext : DbContext
{
public DbSet<SomeEntity> SomeEntities { get; set; }
public FakeContext()
{
}
}
最后的测试类
[TestClass]
public class ServiceTests
{
[TestMethod]
public void CountEmployee_ShoulReturnCorrectResult()
{
using (ShimsContext.Create())
{
ShimRealcontext.Constructor = context => GenerateFakeContext();
ShimDbContext.AllInstances.Dispose =() => DummyDispose();
Service service = new Service();
int result = service.CountSomeEntites();
Assert.AreEqual(result, 2);
}
}
private FakeContext GenerateFakeContext()
{
FakeContext fakeContext = new FakeContext();
fakeContext.SomeEntities.AddRange(new[]
{
new SomeEntity {Id = 1, Name = "entity1"},
new SomeEntity {Id = 2, Name = "entity2"}
});
return fakeContext;
}
}
当我运行测试时,RealContext
构造正常返回,一个FakeContext
建在GenerateFakeContext()
方法,它包含2 SomeEntities
并返回,但在服务之后,变量ctx
的属性SomeEntities
等于空。
是因为我的变量ctx
被声明为new RealContext()
?但调用RealContext
的构造函数会返回FakeContext()
,那么该变量应该是FakeContext
类型的变量吗?
我做错了什么?还是有没有其他的方式来测试服务而不访问真正的数据库?
在我们的测试中,我们借鉴了EF测试源中的模拟。它在Apache许可证下。 – Eris
谢谢!我不知道这个工具。我会看看 –