【发布时间】:2021-04-29 12:06:11
【问题描述】:
我在单元测试中发现了 .NET dbContext 和范围界定的一些有趣行为,但我无法弄清楚为什么会发生这种情况。希望有人知道这是为什么。
这是来自测试方法。以下是步骤。为了清楚起见,我已尝试对其进行编辑。
- 测试类安装程序添加依赖注入所需的服务,并将数据库创建为 InMemory db,并为测试数据播种。
... add services ...
services.AddDbContext<ApplicationDbContext>(options => options.UseInMemoryDatabase("ApplicationDb"));
_serviceProvider = services.BuildServiceProvider();
_serviceScopeFactory = _serviceProvider.GetRequiredService<IServiceScopeFactory>();
_dbContext = _serviceProvider.GetRequiredService<MyDbContext>();
... seed data ...
- 测试方法修改一些数据,然后调用被测试的目标方法。
//signature: public async Task TargetMethod(SomeTaskDto taskDto, IServiceScopeFactory serviceScopeFactory)
... modify some data using _dbContext created in Setup ...
var _myClass =_serviceProvider.GetRequiredService<MyClass>();
await _myClass.TargetMethod( taskDto, _serviceScopeFactory );
- 然后目标方法使用
_serviceScopeFactory获取数据库上下文并修改一些数据。
using (var scope = serviceScopeFactory.CreateScope())
{
var _db = scope.ServiceProvider.GetService<MyDbContext>();
... changes made by calling test method are visible here.
... modify some data ...
await _db.SaveChangesAsync();
... other stuff ...
} //end scope
- 回到测试方法,调用目标方法后,更改在原来的db上下文中是不可见的:
var entityShouldBeModified = _dbContext.Products.Where( x => x.Id = idOfModifiedEntity ).FirstOrDefault();
//this fails:
Assert.AreEqual( expectedUpdatedValue, entityShouldBeModified.PropertyWhichShouldBeModified );
- 如果我在调用目标方法后修改测试方法以创建新范围,并获取新的数据库上下文,则目标方法中的更新数据现在可见:
using(var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetService<MyDbContext>();
db.SetAuthenticatedUser(_user);
var entityShouldBeModified = db.Products.Where( x => x.Id = idOfModifiedEntity ).FirstOrDefault();
//this works:
Assert.AreEqual( expectedUpdatedValue, entityShouldBeModified.PropertyWhichShouldBeModified );
}
这只是在单元测试中使用 InMemory dbs 发生的事情吗? (我想我真的应该在 Sql Server 数据库上尝试一下。) 即使只是在 InMemory dbs 上,为什么测试方法所做的更改对目标方法可见,而目标方法所做的更改对调用测试方法不可见?
为什么我必须创建一个新的范围和新的数据库上下文才能看到目标方法所做的更改?
谢谢,任何解释表示赞赏。
【问题讨论】:
标签: c# .net-core dependency-injection scope