C# 一次运行所有测试会导致其中一些测试失败,但当它们';如果你一个人被解雇,那么他们工作得很好
我有一个奇怪的问题,每当我运行所有的测试时,我的一些测试都失败了,但是当我一个接一个地启动它们时,一切都正常 下面是在内存数据库中设置种子时失败的代码 它必须将一些C# 一次运行所有测试会导致其中一些测试失败,但当它们';如果你一个人被解雇,那么他们工作得很好,c#,visual-studio,.net-core,xunit,visual-studio-2019,C#,Visual Studio,.net Core,Xunit,Visual Studio 2019,我有一个奇怪的问题,每当我运行所有的测试时,我的一些测试都失败了,但是当我一个接一个地启动它们时,一切都正常 下面是在内存数据库中设置种子时失败的代码 它必须将一些权限s添加到权限表中,然后创建与权限有多对多关系的组s 基本上一个组可以有多个权限,一个权限可以在多个组中使用 但问题是 .Single抛出 序列包含多个元素 当所有测试同时运行时,但当它单独运行时,一切都正常 有什么想法吗 public class Tests : IDisposable { private readonly
权限
s添加到权限
表中,然后创建与权限有多对多关系的组
s
基本上一个组可以有多个权限,一个权限可以在多个组中使用
但问题是
.Single
抛出
序列包含多个元素
当所有测试同时运行时,但当它单独运行时,一切都正常
有什么想法吗
public class Tests : IDisposable
{
private readonly Context _context;
public void Dispose()
{
_context.Database.EnsureDeleted();
}
public Tests()
{
var o = new DbContextOptionsBuilder<Context>();
o.UseInMemoryDatabase("testDb");
_context = new Context(o.Options);
_context.Database.EnsureDeleted();
_context.Database.EnsureCreated();
}
[Fact]
public async void myTest()
{
Initializer.InitializePermissions(_context);
Initializer.InitializeGroups(_context);
(...)
}
}
public static class Initializer
{
public static void InitializePermissions(Context context)
{
var permissionNames = new List<string>
{
"CanCreateNewProduct",
"CanRemoveProduct",
};
foreach (var permission in permissionNames)
{
context.Permissions.Add(new Permission(permission));
}
context.SaveChanges();
}
public static void InitializeGroups(Context context)
{
var groups = new Dictionary<string, List<string>>();
groups.add("Admin", new List<string>{"CanRemoveProduct"};
foreach (var group in groups)
{
foreach (var permissionName in group.Value)
{
var permission = context.Permissions.Single(x => x.Name == permissionName);
group.GroupPermissions.Add
(
new Many2Many
{
Group = group,
GroupId = group.Id,
Permission = permission,
PermissionId = permission.Id
}
);
}
context.Groups.Add(new Group(group.Key, permissions);
}
context.SaveChanges();
}
}
公共类测试:IDisposable
{
私有只读上下文\u上下文;
公共空间处置()
{
_context.Database.EnsureDeleted();
}
公开考试()
{
var o=new DbContextOptionsBuilder();
o、 使用MemoryDatabase(“testDb”);
_上下文=新上下文(o.Options);
_context.Database.EnsureDeleted();
_context.Database.recreated();
}
[事实]
公共异步void myTest()
{
InitializePermissions(_context);
初始化器。初始化组(_上下文);
(...)
}
}
公共静态类初始值设定项
{
公共静态void InitializePermissions(上下文)
{
var permissionNames=新列表
{
“CanCreateNewProduct”,
“CanRemoveProduct”,
};
foreach(permissionNames中的var权限)
{
context.Permissions.Add(新权限(Permission));
}
SaveChanges();
}
公共静态void初始化组(上下文)
{
var groups=newdictionary();
添加(“管理员”,新列表{“CanRemoveProduct”};
foreach(组中的var组)
{
foreach(group.Value中的var permissionName)
{
var permission=context.Permissions.Single(x=>x.Name==permissionName);
group.GroupPermissions.Add
(
新的许多
{
组=组,
GroupId=group.Id,
权限=权限,
PermissionId=permission.Id
}
);
}
context.Groups.Add(新组(Group.Key,权限);
}
SaveChanges();
}
}
这里的问题是您的测试使用的是共享状态
(顺便说一句,如果你想知道为什么很多程序员会不遗余力地避免使用任何static
,你会觉得他们的对象、依赖注入等过于复杂,而他们只能“使其成为静态”…这就是原因。)
您的初始值设定项
可能会保持静态
,只要它不在内部维护状态。由于您将数据库上下文的实例传递给它,因此它看起来至少不是一眼就能看到的。但是,当您继续在系统中工作时,必须保持此初始值设定项本身不维护任何状态ss测试
这就引出了内存中数据库本身:
o.UseInMemoryDatabase("testDb");
这些可在整个应用程序中全局访问。但您可以为它们指定唯一的名称。例如:
var dbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(dbName);
这样,每个数据库上下文都应该有一个唯一的数据库,您可以在以后使用dbName
在任何需要的地方引用该数据库。因此,即使所有数据库在技术上都是全局可用的,任何给定的测试都只知道自己的数据库,并且只能引用自己的数据库
(当然要注意性能。如果您发现自己正在创建大型复杂数据库,而这不应该用于小型的单个测试,那么一次创建许多数据库可能会降低速度。)这里的问题是您的测试正在使用共享状态 (顺便说一句,如果你想知道为什么很多程序员会不遗余力地避免使用任何
static
,你会觉得他们的对象、依赖注入等过于复杂,而他们只能“使其成为静态”…这就是原因。)
您的初始值设定项
可能会保持静态
,只要它不在内部维护状态。由于您将数据库上下文的实例传递给它,因此它看起来至少不是一眼就能看到的。但是,当您继续在系统中工作时,必须保持此初始值设定项本身不维护任何状态ss测试
这就引出了内存中数据库本身:
o.UseInMemoryDatabase("testDb");
这些可在整个应用程序中全局访问。但您可以为它们指定唯一的名称。例如:
var dbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(dbName);
这样,每个数据库上下文都应该有一个唯一的数据库,您可以在以后使用dbName
在任何需要的地方引用该数据库。因此,即使所有数据库在技术上都是全局可用的,任何给定的测试都只知道自己的数据库,并且只能引用自己的数据库
(当然要注意性能。如果您发现自己正在创建大型复杂数据库,而这不应该用于小型的单独测试,那么一次创建许多这样的数据库可能会降低速度。)听起来您的测试是共享状态。每个测试都应该完全隔离,不依赖于外部或共享状态。可能不使用单一的
静态
内存结构,而是使用相同的结构,但基于实例,每个测试创建/使用/处置自己的实例?每个数据库也需要隔离,因此 UseInMemoryDatabase(“testDb”)
需要为每个测试提供单独的数据库名称。将UseInMemoryDatabase(“testDb”)
更改为UseInMemoryDatabase(Guid.NewGuid().ToString());
已完成