C# 使用基类进行集成测试

C# 使用基类进行集成测试,c#,unit-testing,integration-testing,C#,Unit Testing,Integration Testing,集成测试的我的基类: [TestClass] public class BaseIntegrationTest { protected readonly ApplicationDbContext _dbContext; public BaseIntegrationTest() { _dbContext = new ApplicationDbContext("DefaultConnectionTest"); } [ClassInitial

集成测试的我的基类:

[TestClass]
public class BaseIntegrationTest
{
    protected readonly ApplicationDbContext _dbContext;

    public BaseIntegrationTest()
    {
        _dbContext = new ApplicationDbContext("DefaultConnectionTest");
    }

    [ClassInitialize]
    public void Initialize()
    {
        InsertTestData();
    }

    public void InsertTestData()
    {
        _dbContext.Users.Add(new User { Name = "John Doe" });
    }
}
下面是一个从
BaseIntegrationTest
继承的测试类:

[TestClass]
public class UserRepositoryTests : BaseIntegrationTest
{
    // how to lose this method here and use the one in the BaseIntegrationTest?
    //[ClassInitialize]
    //public static void Setup(TestContext context)
    //{
    //  BaseIntegrationTest test = new BaseIntegrationTest();
    //  test.InsertTestData();
    //}

    [TestMethod]
    public void GetUser()
    {
        Filter f = new Filter()
        {
            Name = "John Doe"
        };

        UserRepository fr = new UserRepository(_dbContext);
        var result = fr.GetUser(f);

        Assert.IsTrue(result.Any(x => x.Name == "John Doe"));
    }
}
BaseIntegrationTest
中用
[ClassInitialize]
属性修饰的方法永远不会执行,因此,我的测试失败。没有数据被插入到数据库中

但是,如果我在
UserRepositoryTests
中取消对
公共静态无效设置(TestContext context)
的注释,它就会工作

我还有几个要测试的存储库。我希望在基类中完成将数据插入数据库的操作,这样我就可以运行所有测试,而无需为每个要测试的存储库重新创建数据库

public void Initialize()
转换为
public static void Initialize(TestContext上下文)
也不起作用。
Initialize()
不会被执行/调用

我错过什么了吗?或者这些是单元测试/集成测试的限制?我对单元测试/集成测试非常陌生。

来自MSDN:

[TestInitialize]
相同的方法是否适用于
[ClassInitialize]
在基类中

如果在中创建
[ClassInitialize]
属性化方法,则不完全是这样 除非显式调用基类,否则它永远不会被调用 在派生测试类开始时,初始化
ClassInitialize
方法;当然,这远不如上述方法好

稍后将介绍如何在继承类中的任何方法之前进行初始化:

如何创建将在任何 我的测试项目中的类初始化方法

基于上述通用基类方法,您可以 只需向基类添加一个静态构造函数,然后执行 此处的初始化或调用将执行 所需的初始化。生成的基类可能如下所示 这:


虽然此模式适用于nunit,但它似乎不适用于mstest,因为无法继承ClassInitializeAttribute

解决方法之一是在基类的构造函数中进行初始化

比如:

[TestClass]
public class BaseIntegrationTest
{
    protected readonly ApplicationDbContext _dbContext;

    public BaseIntegrationTest()
    {
        _dbContext = new ApplicationDbContext("DefaultConnectionTest");
         InsertTestData();
    }

    public void InsertTestData()
    {
        _dbContext.Users.Add(new User { Name = "John Doe" });
    }
}
您可以添加一个静态标志,以防止它运行每个测试:

[TestClass]
public class BaseIntegrationTest
{
    private static bool _testsInitialized = false;

    protected readonly ApplicationDbContext _dbContext;

    public BaseIntegrationTest()
    {
        if(!_testsInitialized) {
            _dbContext = new ApplicationDbContext("DefaultConnectionTest");
             InsertTestData();
            _testsInitialized = true;
        }
    }

    public void InsertTestData()
    {
        _dbContext.Users.Add(new User { Name = "John Doe" });
    }
}

…非常不雅观,但可能比将静态设置为ApplicationDbContext(以及从静态构造函数调用的所有其他方法)更雅致。

您已经获得了我的支持,但我会从链接源中提取一个片段,以防将来链接会断开。如果我从静态构造函数调用
InsertTestData()
,然后我还必须使
InsertTestData()
静态,以及从静态构造函数调用的所有其他方法。这很管用,但我怀疑它是否优雅。谢谢这是我最初的方法,但是构造函数会在每个正在执行的测试方法上执行。因此插入dublicate数据,或者至少尝试这样做,因为我在用户表中有唯一的索引。它抛出了一个错误。我编辑了答案以提供一个解决方案——比将所有方法/变量都静态化稍微优雅一些,这也会失败,因为对于您运行的每个测试方法,整个基类似乎都是“重置”的。因此
\u testsInitialized=true实际上永远不会保持为真。下一个将要执行的测试方法,它的默认值是false,正如您所声明的那样。我必须补充一点,这是我已经尝试过的事情之一。
[TestClass]
public class BaseIntegrationTest
{
    private static bool _testsInitialized = false;

    protected readonly ApplicationDbContext _dbContext;

    public BaseIntegrationTest()
    {
        if(!_testsInitialized) {
            _dbContext = new ApplicationDbContext("DefaultConnectionTest");
             InsertTestData();
            _testsInitialized = true;
        }
    }

    public void InsertTestData()
    {
        _dbContext.Users.Add(new User { Name = "John Doe" });
    }
}