下午好!我有一个 asp.net mvc web 应用程序。为了使用数据库,我使用了一个通过实体框架与数据库通信的存储库类。我决定为 Repository 类编写单元测试,为此,我没有使用特定的数据上下文类,而是使用依赖注入实现了一个接口。是这样的:
public class MyContext: DbContext
{
DbSet<Foo> Foo { get; set; }
}
public class Repository
{
private MyContext _context;
public Repository()
{
_context = new MyContext();
}
public Foo GetFoo(int id)
{
return _context.Foo.Find(id);
}
}
变成了这样:
public interface IMyContext
{
DbSet<Foo> Foo { get; set; }
}
public class MyContext: DbContext, IMyContext
{
DbSet<Foo> Foo { get; set; }
}
public class Repository
{
private IMyContext _context;
public Repository(IMyContext context)
{
_context = context;
}
public Foo GetFoo(int id)
{
return _context.Foo.Find(id);
}
}
一切似乎都很好——存储库对上下文的具体实现一无所知,您可以将假上下文插入其中以进行测试。但并非一切都如此简单。如您所见,接口本身“了解”此类实体,DbSet<T>以及 EntityFramework 的其他细节,为简洁起见,上述代码中省略了这些细节。也就是说,包含单元测试的项目需要包含 EntityFramework 包。这在多大程度上是正确的?还是需要以其他方式测试存储库?
好的,为了避免另一个不在主题“并且你创建一个 IRepository 接口”中的答案,我将尝试描述 Mayorov 评论的本质:
存储库(从某种意义上说,通常嵌套在具有 EF 的应用程序中的这种模式中)是请求的集合。你:
FindByIQueryable,你总是在这些方法的实现中做ToList()//First()等等-你总是物化请求的结果您可以通过将实现替换为测试存储库来测试存储库使用单元测试的所有代码。
您可以使用集成测试、实时基础和真正的 EF 来测试存储库本身。
可以使用单元测试来测试存储库,但这非常困难且毫无意义。什么可能出错以及测试可以揭示什么:
您应该为存储库编写具有真实基础的集成测试,或者根本不编写它们。
不要用
DbContext-th 绑定接口。使用通用接口:和实现
EntityFramework:然后一切都很容易。
EFRepository用于接口上的测试寄存器IRepositoryEntity。这样你就不需要添加链接到EntityFramework您试图在测试中不仅包括应用程序的逻辑,还包括对第三方服务 (EF) 的测试。@Chloroform 的接口实现是正确的。利益必须从一切事物中抽离出来。但是服务的实现可以使用任何东西。虽然是 ADO,虽然是 EF。
根据我的经验,唯一合适的选择是使用 Mock/Microsoft Fakes 框架
第一个作为插件提供,并没有像 Fakes 那样的所有实现。但如果你没有公司执照,就没有其他出路了。
带有模拟示例的理论 https://metanit.com/sharp/mvc5/18.5.php
假货 https://msdn.microsoft.com/en-us/library/hh549175.aspx
这将是一种简单的方法来覆盖不受控制的方法的返回值。