为什么单独的 DbContexts 在单元测试期间修改同一个 DbSet?
Why are separate DbContexts modifying the same DbSet during Unit Tests?
环境:
Xunit 2.3.1
Microsoft.EntityFrameworkCore.InMemory 2.1.0
我在三种不同的class中有三种测试方法,当运行单独通过但当运行一起时,只有一个会通过,另外两个会失败。然后当两者再次 运行 时 - 一个将通过,另一个将失败。
我发现了这个问题,只是不确定为什么会这样。
我将展示一些代码,代码下方是设计说明。
要点:
三个测试classes:
public class FirstReviewRepoTest
public class SecondReviewRepoTest
public class ThirdReviewRepoTest
测试方法(都是同名的):
public void GetReviewDataTest(){}
public void GetReviewDataTest(){}
public void GetReviewDataTest(){}
查看下面充实的测试之一的更多代码:
[Trait("Repo","")]
public class FirstReviewRepoTest{
[Fact(DisplayName = "GetReviewDataTest")]
[Trait("Repo","FirstReviewRepo")]
pubic void GetReviewDataTest(){
var options = new DbContextOptionsBuilder<MyAppDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
using (MyAppDbContext context = new MyAppDbContext(options)){
SeedDb(context);
AddData(context);
FirstReviewRepository repository = new FirstReviewRepository(context);
FirstReviewDM dm = repository.GetReviewData(context.ItemInstanceDocumentInstance.Last().Id);
FirstReviewDM expected = new FirstReviewDM{
Analysis = "Analysis",
Comments = "Comments",
Solution = "Solution",
Review = "Review",
ReviewerToApproved = new KeyValuePair<string,bool>
}
Assert.Equal(expected,dm);
}
private void SeedDb(MyAppDbContext){
CreateDocumentDescriptions(context);
CreateTaskDescriptions(context);
CreateDocumentFieldDescriptions(context);
//... These go on...
AddUsersWithRoleData(context); //This is where the issue begins
context.SaveChanges();
}
private void AddUsersWithRoleData(MyAppDbContext context){
List<Users> users = new List<Users>()
{
new Users { Name = "user1" },
new Users { Name = "user2" },
new Users { Name = "user3" },
new Users { Name = "user4" },
new Users { Name = "user5" },
new Users { Name = "user6" },
new Users { Name = "user7" },
new Users { Name = "user8" }
{
}
设计说明:
最初,测试 class 全部继承自定义 SeedDb(MyAppDbContext)
及其所有包含方法的基 class。
基础 class 也有一个名为 GetContextWithData()
的方法,它返回一个新的 MyAppDbContext
,它的表是通过 SeedDb()
填充的
我把它全部移走了,因为担心继承搞砸了。
问题:
所有三个测试方法都创建一个存储库对象并调用一个方法来获取各自的评论数据。在这些方法中,调用 Users dbSet,例如_context.Users.Single(x=> x.Id == document.AuthorId)
。在所有三个测试中,document.AuthorId 等于 5。不知何故,AddUsersWithRoleData
的所有三个调用都将用户添加到看似相同的 DbSet<Users>
因此,只有一个 DbSet 具有 Id = 5 的用户。
我试过:
按顺序进行测试运行。 不起作用
在添加到 DbContext 时为用户声明 ID。 修复了这个问题,但破坏了将用户添加到 DbSet 的其他测试
ID 未重置的原因是 EfCore.InMemory(2.1) 中的 InMemory 数据库共享密钥生成的值。这背后的原因是他们与 Db 无关。
这个讨论可以深入here
环境:
Xunit 2.3.1
Microsoft.EntityFrameworkCore.InMemory 2.1.0
我在三种不同的class中有三种测试方法,当运行单独通过但当运行一起时,只有一个会通过,另外两个会失败。然后当两者再次 运行 时 - 一个将通过,另一个将失败。
我发现了这个问题,只是不确定为什么会这样。
我将展示一些代码,代码下方是设计说明。
要点:
三个测试classes:
public class FirstReviewRepoTest
public class SecondReviewRepoTest
public class ThirdReviewRepoTest
测试方法(都是同名的):
public void GetReviewDataTest(){}
public void GetReviewDataTest(){}
public void GetReviewDataTest(){}
查看下面充实的测试之一的更多代码:
[Trait("Repo","")]
public class FirstReviewRepoTest{
[Fact(DisplayName = "GetReviewDataTest")]
[Trait("Repo","FirstReviewRepo")]
pubic void GetReviewDataTest(){
var options = new DbContextOptionsBuilder<MyAppDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
using (MyAppDbContext context = new MyAppDbContext(options)){
SeedDb(context);
AddData(context);
FirstReviewRepository repository = new FirstReviewRepository(context);
FirstReviewDM dm = repository.GetReviewData(context.ItemInstanceDocumentInstance.Last().Id);
FirstReviewDM expected = new FirstReviewDM{
Analysis = "Analysis",
Comments = "Comments",
Solution = "Solution",
Review = "Review",
ReviewerToApproved = new KeyValuePair<string,bool>
}
Assert.Equal(expected,dm);
}
private void SeedDb(MyAppDbContext){
CreateDocumentDescriptions(context);
CreateTaskDescriptions(context);
CreateDocumentFieldDescriptions(context);
//... These go on...
AddUsersWithRoleData(context); //This is where the issue begins
context.SaveChanges();
}
private void AddUsersWithRoleData(MyAppDbContext context){
List<Users> users = new List<Users>()
{
new Users { Name = "user1" },
new Users { Name = "user2" },
new Users { Name = "user3" },
new Users { Name = "user4" },
new Users { Name = "user5" },
new Users { Name = "user6" },
new Users { Name = "user7" },
new Users { Name = "user8" }
{
}
设计说明:
最初,测试 class 全部继承自定义 SeedDb(MyAppDbContext)
及其所有包含方法的基 class。
基础 class 也有一个名为 GetContextWithData()
的方法,它返回一个新的 MyAppDbContext
,它的表是通过 SeedDb()
我把它全部移走了,因为担心继承搞砸了。
问题:
所有三个测试方法都创建一个存储库对象并调用一个方法来获取各自的评论数据。在这些方法中,调用 Users dbSet,例如_context.Users.Single(x=> x.Id == document.AuthorId)
。在所有三个测试中,document.AuthorId 等于 5。不知何故,AddUsersWithRoleData
的所有三个调用都将用户添加到看似相同的 DbSet<Users>
因此,只有一个 DbSet 具有 Id = 5 的用户。
我试过:
按顺序进行测试运行。 不起作用
在添加到 DbContext 时为用户声明 ID。 修复了这个问题,但破坏了将用户添加到 DbSet 的其他测试
ID 未重置的原因是 EfCore.InMemory(2.1) 中的 InMemory 数据库共享密钥生成的值。这背后的原因是他们与 Db 无关。
这个讨论可以深入here