简体   繁体   中英

Multiple TestInitialize attributes in MSTEST

Using MSTEST in VS2012.3 .NET4.5 and R# for the test runner.

The code below works in the order 1,2,3,4.

However I'm concerned that it may not always execute in this order as multiple TestInitialize attributes are not supported MSDN

Question: Is this allowed, and do the docs just mean that multiple TestInitialize attributes are not allowed in the same class?

I would like to keep this structure as have many integration tests inheriting off TransactedTestBase, yet requiring different SQL scripts to setup.

Same behaviour was found here

[TestClass]
public class DelegationTest : TransactedTestBase
{
    [TestInitialize]
    public void Setup()
    {
        Console.WriteLine("2 Setup");
        //var script = "INSERT INTO blah...";
        //var sqlConnect = new SqlConnection(dbConnection.ConnectionString);
        //sqlConnect.Open();
        //var server = new Server(sqlConnect);
        //var database = server.Databases[sqlConnect.Database];
        //database.ExecuteNonQuery(script);
    }

    [TestMethod]
    public void TestMethod1()
    {
        Console.WriteLine("3 Test Method");
    }
}

[TestClass]
public class TransactedTestBase
{
    //protected userEntities userEntities;
    //private TransactionScope scope;
    //public static SqlDatabase dbConnection;

    //private const bool ShouldWriteToDB = true;
    //private const bool ShouldWriteToDB = false;

    [TestInitialize()]
    public virtual void TestStart()
    {
        Console.WriteLine("1 TestStart");
        //if (ShouldWriteToDB)
        //{
        //    dbConnection = EnterpriseLibraryContainer.Current.GetInstance<SqlDatabase>("DBConnect");
        //    return;
        //}

        //scope = new TransactionScope(TransactionScopeOption.RequiresNew);
        //user = new userEntities();
        //dbConnection = EnterpriseLibraryContainer.Current.GetInstance<SqlDatabase>("DBConnect");
    }

    [TestCleanup()]
    public virtual void TestEnd()
    {
        Console.WriteLine("4 TestEnd");
        //if (ShouldWriteToDB) return;

        //scope.Dispose();
    }
}

I believe the docs are referring to using the TestInitializeAttribute multiple times on the same method. This is controlled by the AttributeUsage(AllowMultiple=false) . FWIW, I have a medium size test suite (~200 tests) predicated on the code you've shown working as you are expecting: TestStart is called before Setup .

There are issues with making the TestInitialize method virtual and overriding it (see here ) and inheritance of ClassInitialize methods ( MsTest ClassInitialize and Inheritance ).

I believe you misread the MSDN article. They state:

This attribute can be specified on a method. Only one instance of this attribute may be applied to a method.

Which means that you can not have code like this:

[TestInitialize]
[TestInitialize]
public void MyIntilialzer(){}

It does not mean you can't have multiple initializers, even in the same class.

I'm not sure about MSTest, but in NUnit its well defined that in the situation you describe, the initializers will be ran in the right order, from base class up. And if you have few initializers in the same class, the order is not guaranteed.

I would assume this is true for MSTest as well (but I don't have reference point).

Be aware that the executing order depends on test runner. Visual Studio test runner and R# test runner might behave differently. Now I believe they have the same behavior, but still it is up to R# how it will behave.

I remember that one of R# old version has a bug and TestInitialize method from subclass was executed earlier then TestInitialize method in base class. Of course, it was fixed quickly :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM