Can a TestActionAttribute in NUnit run BeforeTest before the fixture's own SetUp method?
Asked Answered
H

1

10

I have some old MbUnit code which looks like this:

public class MyFixture {

    [SetUp]
    public void SetUp() {
        // Add data to database
    }

    [Test, Rollback]
    public void DoTest() {
        // Tests with the data
    }
}

My new NUnit Rollback attribute looks a bit like this:

public class RollbackAttribute : TestActionAttribute
{
    public override void BeforeTest(TestDetails testDetails)
    {
        // Begin transaction
    }

    public override void AfterTest(TestDetails testDetails)
    {
        // Abort transaction
    }
}

The Rollback should roll back the new data added in the SetUp method as well as any modifications during the test itself. Unfortunately, it seems that NUnit's BeforeTest runs after the fixture's SetUp method, so the data added during SetUp is not rolled back.

Is there a way to run BeforeTest before SetUp?

One option would be a base class, and replace the existing Rollback attributes with additional code in SetUp and TearDown, however some of my tests require running outside a transaction (they create multiple transactions themselves during the test run), so adding transactions around all test cases would require a bit of care. I'd rather find a solution which can re-use the existing Rollback attributes.

Holter answered 10/7, 2015 at 13:52 Comment(0)
G
5

Is there a way to run BeforeTest before SetUp?

I don't think so, see e.g. this related discussion on google groups. Issue being discussed there is very similar, as you can see, code in SetUp method would run even prior to BeforeTest method used on test fixture level (you have it on test level).

Workaround from my point of view would be to remove the SetUpAttribute from the SetUp method and call the SetUp method explicitly at the beginning of the each test, i.e.:

public class MyFixture
{
    public void SetUp()
    {
        // Add data to database
    }

    [Test, Rollback]
    public void DoTest()
    {
        SetUp();

        // Tests with the data
    }
}

Your question also reminded me of question that marc_s raised in this SO thread. Question is unrelated to your problem, but he used the same construct as I am proposing above so it is perhaps not that bad idea.

EDIT:

Here is an opened issue on NUnit's github. But still, requested order there is:

BeforeTest (BaseFixture)
BaseSetUp BeforeTest (Fixture)
SetUp
BeforeTest (Test)
Test AfterTest (Test)
TearDown AfterTest (Fixture)
BaseTearDown AfterTest (BaseFixture)

So not exactly what you desire, "BeforeTest (Test)" would be executed after SetUp.

Grissel answered 14/7, 2015 at 0:19 Comment(3)
Yes, I think the initial implementation I'm refactoring was a bit backwards - the per-fixture SetUp method shouldn't be relying on a per-test attribute to ensure that its state is cleaned up properly, so it is entirely reasonable to have to change that.Holter
There is no affiliation. I will be awarding the bounty once I've finished my own stuff and concluded that this answer works for me.Unbuckle
@Unbuckle ah, I see, thanks, I thought you two are co-workers.Grissel

© 2022 - 2024 — McMap. All rights reserved.