XUnit:ICollectionFixture 实例未在测试的测试方法之间共享 class
XUnit: ICollectionFixture instance not getting shared between test methods of a test class
我创建了 ICollectionFixture 实现,希望创建一个数据库实例并在各种测试 classes 之间共享它。但是,它并没有发生,并且在每次测试方法调用时都会创建 DBContext。在调试时,我可以清楚地看到在每个测试方法完成后,我的 InMemoryDbContextFixture class 的 Dispose 方法被调用,所以每次都会创建一个新的 DBContext 实例,它不会保存我传递的任何数据通过我的第一个测试方法..
XUnit 文档明确指出,当您想创建单个测试上下文并在多个测试 classes 中的测试之间共享它时,我们可以创建 ICollectionFixture 实现。
当我们总是在创建 DBContext 的新实例时,共享意味着什么?请以共享实例的名义帮助我理解这种行为。
我可以使用
实现目前的行为
Static classes
as well. So why to use ICollectionFixture. This interface should prevent me from creating new instance of DBContext for every test case.
我的灯具 class 是这样的
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.
}
我的测试Class
//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);
}
}
}
是的,在运行一次性完成所有测试用例后,我得到了答案..
实际上,当我们试图只测试一个测试方法而不是整个测试项目时,我们可能会遇到这个问题。我很困惑,因为在测试 class.
中尝试单独调试测试方法时
现在,当我 运行 visual studio 中的所有 运行 案例时,我可以清楚地看到 ICollectionFixture
实例仅创建一次并在各种测试之间共享 classes 使用集合。
我创建了 ICollectionFixture 实现,希望创建一个数据库实例并在各种测试 classes 之间共享它。但是,它并没有发生,并且在每次测试方法调用时都会创建 DBContext。在调试时,我可以清楚地看到在每个测试方法完成后,我的 InMemoryDbContextFixture class 的 Dispose 方法被调用,所以每次都会创建一个新的 DBContext 实例,它不会保存我传递的任何数据通过我的第一个测试方法..
XUnit 文档明确指出,当您想创建单个测试上下文并在多个测试 classes 中的测试之间共享它时,我们可以创建 ICollectionFixture 实现。
当我们总是在创建 DBContext 的新实例时,共享意味着什么?请以共享实例的名义帮助我理解这种行为。 我可以使用
实现目前的行为Static classes as well. So why to use ICollectionFixture. This interface should prevent me from creating new instance of DBContext for every test case.
我的灯具 class 是这样的
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.
}
我的测试Class
//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);
}
}
}
是的,在运行一次性完成所有测试用例后,我得到了答案..
实际上,当我们试图只测试一个测试方法而不是整个测试项目时,我们可能会遇到这个问题。我很困惑,因为在测试 class.
中尝试单独调试测试方法时现在,当我 运行 visual studio 中的所有 运行 案例时,我可以清楚地看到 ICollectionFixture
实例仅创建一次并在各种测试之间共享 classes 使用集合。