我们创建了一个 API,它将从数据库中创建的 SQL 视图中获取数据。
这是存储库代码:
List<Entities.MyView> reportsData = await (
from r in _context.MyView
where r.UserKey == userKey
select r)
.ToListAsync(cancellationToken);
现在,我们需要为我们的存储库测试实现单元测试。
这是数据库设置:
protected void SetUp()
{
services.AddDbContext<UrpContext>(options =>
{
options.UseInMemoryDatabase("My_Database");
});
services.AddReportsPersistence();
provider = services.BuildServiceProvider();
// Clear the Database if exists any in context
using (var scope = provider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<UrpContext>();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
}
}
我们正在使用示例数据为用于视图的表播种。在上下文中,我们看到数据已成功添加到表中。但是当涉及到存储库和获取数据时,它显示我的视图没有任何数据。
我发现,当使用内存数据库进行测试时,视图并未具体化,因此我们需要在测试设置中模拟视图逻辑。是的,该视图不会随着数据添加到表中而更新/刷新。
对于我需要测试存储库逻辑的场景,是否有任何推荐的方法来实现单元测试? (只有在测试中使用SQLite创建视图才是解决方案?)
这是我如何向其中一个表添加数据的示例
User
:
var context = provider.GetRequiredService<UrpContext>();
User user = new User
{
UserId = userId,
Email = $"user{userKey}@org.in"
};
context.User.Add(user);
context.SaveChanges();
简短的回答:不要尝试对存储库模式进行单元测试。这可以通过集成测试来覆盖,该测试涵盖了真实数据库的完整端到端场景。为了设置这样的集成测试,我建议使用与生产中使用的相同的 DBMS。使用集成测试将运行的表和种子数据创建实例的备份,并恢复为每个测试套件运行所保留的命名实例。备份不需要是完整的数据库。您可以使用多个带有相关表和数据的分段数据库来为一个或多个测试套件提供服务。 使用与生产相同的 DBMS 和相同的设置,以确保您不会错过可能由排序规则、区域设置等引起的问题。这些还可以提供性能指标并提示问题以及索引使用等详细信息,参数嗅探。针对不同的 DBMS 进行测试可能会产生显着不同的行为。
单元测试应该很快,这样您就可以在增量开发时定期运行它们。集成测试将作为持续集成过程的一部分或在候选版本之前运行,因为它们需要更多时间来设置和运行实际数据场景,需要几分钟才能运行完毕。
采用存储库模式的一个关键原因是作为单元测试的边界。目标是它是一个可以模拟的依赖项,以便您可以测试实际的业务逻辑,因此它应该是 EF 的轻量级抽象。您不应该对视图进行单元测试,或者 EF 是否执行其应有的操作。单元测试涵盖“当我的存储库返回时,我的代码是否执行我期望的操作......<- (insert mocked data scenario here)"