使用基类进行集成测试

时间:2015-02-17 09:31:15

标签: c# unit-testing integration-testing

我的集成测试基类:

[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"));
    }
}

[ClassInitialize]中用BaseIntegrationTest属性修饰的方法永远不会被执行,因此,我的测试失败了。没有数据插入数据库。

但是,如果我取消注释public static void Setup(TestContext context)中的UserRepositoryTests,那就可以了。

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

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

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

2 个答案:

答案 0 :(得分:3)

来自MSDN:

  

[TestInitialize]使用的方法相同吗?   基类中的[ClassInitialize]

     

如果您在中创建[ClassInitialize]归因方法,则不完全一样   除非你明确地调用它,否则它将永远不会被调用   在派生测试类的开头ClassInitialize   方法;这当然远不如上述方法那么好。

http://blogs.msdn.com/b/densto/archive/2008/05/16/using-a-base-class-for-your-unit-test-classes.aspx

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

  

如何创建一个在任何之前运行的初始化方法   我的测试项目中的类初始化方法?

     

基于上面描述的通用基类方法,您可以   只需向基类添加一个静态构造函数即可执行   在那里初始化或调用将执行的方法   期望初始化。生成的基类可能看起来像   这样:

[TestClass]
public class TestBase
{
    static TestBase()
    {
        s_log = new StringBuilder();
        Log.AppendLine("TestBase.ctor()");
    }

    [TestInitialize]
    public void BaseTestInit()
    {
        Log.AppendLine("TestBase.BaseTestInit()");
    }

    [TestCleanup]
    public void BaseTestCleanup()
    {
        Console.WriteLine(Log.ToString());
    }

    public static StringBuilder Log
    {
        get { return s_log; }
    }

    static StringBuilder s_log;
} 

答案 1 :(得分:0)

虽然这种模式适用于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(以及从静态ctor调用的所有其他方法)更优雅