【问题标题】:Running all tests at once result in some of them failing, but when they're being fired alone, then they work fine一次运行所有测试会导致其中一些测试失败,但是当它们被单独解雇时,它们可以正常工作
【发布时间】:2019-06-18 11:55:35
【问题描述】:

我有一些奇怪的问题,每当我 Run all 测试时,我的一些测试都会失败,但是当我一个接一个地启动它们时,一切正常

这里的代码在播种 InMemoryDatabase 时失败

它必须在Permissions 表中添加一些Permissions,然后创建与权限具有多对多关系的Groups

基本上一个Group可以有多个权限,一个权限可以在多个组中使用

但问题是

.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();
    }
}

【问题讨论】:

  • 听起来您的测试正在共享状态。每个测试都应该完全隔离,不依赖于外部或共享状态。也许不是使用单个static 内存结构,而是使用相同的结构但基于实例,并且每个测试都创建/使用/处置自己的实例?每个数据库也需要隔离,因此UseInMemoryDatabase("testDb") 需要为每个测试提供单独的数据库名称。
  • UseInMemoryDatabase("testDb") 更改为UseInMemoryDatabase(Guid.NewGuid().ToString()); 就足够了哦,谢谢!如果你愿意,那就把它写成答案,这样我就可以接受了

标签: c# visual-studio .net-core xunit visual-studio-2019


【解决方案1】:

这里的问题是您的测试使用共享状态。

(顺便说一句,如果你想知道为什么很多程序员会竭尽全力避免使用任何东西 static 并且你觉得他们的对象、依赖注入等过于复杂,而他们可以“制作”静态”...这就是原因。)

你的Initializer 可以可能保持static,只要它不内部保持状态。至少一目了然,因为您将数据库上下文的实例传递给它。但是,当您继续在系统中工作时,重要的是要保持此初始化程序在测试中不维护任何状态。

这将我们带到内存数据库本身:

o.UseInMemoryDatabase("testDb");

这些可以在整个应用程序中全局访问。 但是你可以给他们唯一的名字。例如:

var dbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(dbName);

有了这个,每个数据库上下文都应该有一个唯一的数据库,您以后可以在任何需要的地方使用dbName 引用它。因此,即使所有数据库在技术上都是全球可用的,但任何给定的测试都只知道自己的,并且只能引用自己的。

(当然要注意性能。如果您发现自己创建了大型复杂数据库,而您不应该将其用于小型个人测试,那么同时创建 许多 个这些数据库可能会减慢速度.)

【讨论】:

    猜你喜欢
    • 2018-03-27
    • 2011-10-23
    • 2012-12-16
    • 1970-01-01
    • 2015-02-19
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多