首页 > 解决方案 > 一次运行所有测试会导致其中一些测试失败,但是当它们被单独解雇时,它们可以正常工作

问题描述

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

这是播种失败的代码InMemoryDatabase

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

基本上一个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();
    }
}

标签: c#visual-studio.net-corexunitvisual-studio-2019

解决方案


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

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

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

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

o.UseInMemoryDatabase("testDb");

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

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

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

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


推荐阅读