运行 一次所有测试都会导致其中一些测试失败,但是当它们被单独触发时,它们就可以正常工作
Running all tests at once result in some of them failing, but when they're being fired alone, then they work fine
我有一些奇怪的问题,每当我 Run all
测试时,我的一些测试都会失败,但是当我一个接一个地启动它们时,一切正常
这是播种失败的代码 InMemoryDatabase
它必须添加一些 Permission
到 Permissions
table 然后创建 Group
与权限
有多对多关系
基本上一个组可以有多个权限,一个权限可以在多个组中使用
但问题是
.Single
抛出
Sequence contains more than one element
当所有测试同时 运行 时,但单独 运行 时一切正常
有什么想法吗?
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();
}
}
这里的问题是您的测试正在使用共享状态。
(顺便说一句,如果你想知道为什么很多程序员会竭尽全力避免使用任何东西 static
并且你觉得他们的对象,依赖注入等在他们可以使用的时候过于复杂只是 "make it static"... 这就是原因。)
你的Initializer
可以可能保持static
,只要它不在内部保持状态。至少乍一看似乎不是,因为您将数据库上下文的实例传递给它。但是当你继续在你的系统中工作时,重要的是要保持这个初始化器在测试中不保持任何状态。
这将我们带到 in-memory 数据库本身:
o.UseInMemoryDatabase("testDb");
这些可在整个应用程序中全局访问。 但是您可以为它们指定唯一的名称。例如:
var dbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(dbName);
有了这个,每个数据库上下文都应该有一个唯一的数据库,您以后可以在任何需要的地方使用 dbName
引用它。因此,即使所有数据库在技术上都是全球可用的,任何给定的测试都只知道它自己的并且只能引用它自己的。
(当然要注意性能。如果您发现自己创建了大型复杂的数据库,而对于小型的个人测试则不应该这样做,然后创建 many 这些数据库一次可能会减慢速度。)
我有一些奇怪的问题,每当我 Run all
测试时,我的一些测试都会失败,但是当我一个接一个地启动它们时,一切正常
这是播种失败的代码 InMemoryDatabase
它必须添加一些 Permission
到 Permissions
table 然后创建 Group
与权限
基本上一个组可以有多个权限,一个权限可以在多个组中使用
但问题是
.Single
抛出
Sequence contains more than one element
当所有测试同时 运行 时,但单独 运行 时一切正常
有什么想法吗?
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();
}
}
这里的问题是您的测试正在使用共享状态。
(顺便说一句,如果你想知道为什么很多程序员会竭尽全力避免使用任何东西 static
并且你觉得他们的对象,依赖注入等在他们可以使用的时候过于复杂只是 "make it static"... 这就是原因。)
你的Initializer
可以可能保持static
,只要它不在内部保持状态。至少乍一看似乎不是,因为您将数据库上下文的实例传递给它。但是当你继续在你的系统中工作时,重要的是要保持这个初始化器在测试中不保持任何状态。
这将我们带到 in-memory 数据库本身:
o.UseInMemoryDatabase("testDb");
这些可在整个应用程序中全局访问。 但是您可以为它们指定唯一的名称。例如:
var dbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(dbName);
有了这个,每个数据库上下文都应该有一个唯一的数据库,您以后可以在任何需要的地方使用 dbName
引用它。因此,即使所有数据库在技术上都是全球可用的,任何给定的测试都只知道它自己的并且只能引用它自己的。
(当然要注意性能。如果您发现自己创建了大型复杂的数据库,而对于小型的个人测试则不应该这样做,然后创建 many 这些数据库一次可能会减慢速度。)