首页 > 解决方案 > XUnit:ICollectionFixture 实例未在测试类的测试方法之间共享

问题描述

我创建了 ICollectionFixture 实现,希望创建一个数据库实例并在各种测试类之间共享它。但是,它只是没有发生,并且在每个测试方法调用上都会创建 DBContext。在调试时,我可以清楚地看到,在每次测试方法完成后,我的 InMemoryDbContextFixture 类的 Dispose 方法都会被调用,因此每次都会创建一个新的 DBContext 实例,它不会保存我通过第一次测试的任何数据方法..

XUnit文档明确指出,当您想创建单个测试上下文并在多个测试类的测试之间共享它时,我们可以创建 ICollectionFixture 实现。

当我们总是创建一个新的 DBContext 实例时,共享意味着什么?请以共享实例的名义帮助我理解这种行为。我可以使用

静态类也是如此。那么为什么要使用ICollectionFixture。这个接口应该阻止我为每个测试用例创建新的 DBContext 实例。

我的夹具课就像

 public class InMemoryDbContextFixture : IDisposable
{
    private static bool _isdbInitialized = false;
    static MyDbContext databaseContext = null;
    private readonly object _lock = new object();
    public InMemoryDbContextFixture()
    {            
        lock (_lock)
        {
            if (!_isdbInitialized)
            {
                var options = new DbContextOptionsBuilder<MyDbContext>()
                           .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
                           .Options;

                databaseContext = new MyDbContext(options);

                databaseContext.Database.EnsureDeleted();       //Ensure first old db is deleted.
                databaseContext.Database.EnsureCreated();

                _isdbInitialized = true;        //db is initialized for the first time.

                // ... initialize data in the test database ...
                Context = databaseContext;
            }
           
        }
    }

    public void Dispose()
    {
        this.Context.Dispose();
    }

    public MyDbContext Context
    {
        get { return databaseContext; }
        private set { }
    }
}

ICollectionFixture 实现。

[CollectionDefinition("SharedTestDatabaseDemo")]
public class SharedTestDatabaseDBContextCollection : ICollectionFixture<InMemoryDbContextFixture>
{
    // This class has no code, and should never be created. Its purpose is simply
    // to be the place to apply [CollectionDefinition] and all the
    // ICollectionFixture<> interfaces.
}

我的测试班

//using namespaces
namespace Project.TestControllers
{
    [Collection("SharedTestDatabaseDemo")]
    public class TestAuthController
    {  
        private readonly MyDbContext myDbContext = null;
       

        public TestAuthController(InMemoryDbContextFixture dbcontextForTest)
        {
            //Initialize non-mocked objects.           
            nimblyDbContext = dbcontextForTest.Context;

            //Arrange mocks 

            objAuthCountroller = new AuthController(mock1.Object, configSettings, myDbContext,
               mock2.Object, mock3.Object);
        }

        [Fact]
        public async Task Test_LoginUserWithCorrectCredentials()
        {
            //Arrange dependencies.
            InputModel logincred = new InputModel() {
                Email = "XunitTestUser@testmail.com",
                Password = "Pass@9799",
                RememberMe = true
            };

            myDbContext.AspNetUserTokens.Add(new AspNetUserTokens
            {
                UserId = "2",
                LoginProvider = "JWT",
                Name = "XunitTestUser@testmail.com"
            });

            myDbContext.AspNetUsers.Add(new AspNetUsers
            {
                Id = "2",
                Name = "XunitTestUser1",
                UserName = "XunitTestUser1",
                Email = "XunitTestUser@testmail.com",
                NormalizedEmail = "XUNITTESTUSER@TESTMAIL.COM",
                EmailConfirmed = true
            });
           
            await myDbContext.SaveChangesAsync();
            

            //ACT
            var result = await objAuthCountroller.Login(logincred);
            Assert.NotNull(result);
        }

        [Fact]
        public async Task Test_ShouldNotAuthenticateUserWithInvalidPassword()
        {
            InputModel logincred = new InputModel();

            logincred.Email = "rahul@testmail.com";
            logincred.Password = "InvalidPassword";
            logincred.RememberMe = true;           
           var result = await objAuthCountroller.Login(logincred);
            Assert.NotNull(result);
        }
    }
}

标签: c#.net-corexunit

解决方案


是的,在一次运行所有测试用例时,我得到了答案..

实际上,当我们尝试只测试一个测试方法而不是整个测试项目时,我们可能会遇到这个问题。我很困惑,因为当尝试在测试类中单独调试测试方法时。

现在,当我在 Visual Studio 中运行所有运行案例时,我可以清楚地看到该ICollectionFixture实例仅创建一次,并使用该集合在各种测试类之间共享。


推荐阅读