How to use OneTimeSetup?
Asked Answered
C

3

5

NUnit has a OneTimeSetup attribute. I am trying to think of some scenarios when I can use it. However, I cannot find any GitHub examples online (even my link does not have an example).

Say I had some code like this:

[TestFixture]
public class MyFixture
{
    IProduct Product;

    [OneTimeSetUp]
    public void OneTimeSetUp()
    {
        IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
        Product = fixture.Create<Product>();
    }

    [Test]
    public void Test1()
    {
      //Use Product here
    }

    [Test]
    public void Test2()
    {
      //Use Product here
    }

    [Test]
    public void Test3()
    {
      //Use Product here
    }
}

Is this a valid scenario for initialising a variable inside OneTimeSetup i.e. because in this case, Product is used by all of the Test methods?

Curtain answered 22/1, 2018 at 19:5 Comment(0)
M
6

Yes. No. :-)

Yes... [OneTimeSetUp] works as you expect. It executes once, before all your tests and all your tests will use the same product.

No... You should probably not use it this way, assuming that the initialization of Product is not extremely costly - it likely is not since it's based on a mock.

OneTimeSetUp is best used only for extremely costly steps like creating a database. In fact, it tends to have very little use in purely unit testing.

You might think, "Well if it's even a little more efficient, why not use it all the time?" The answer is that you are writing tests, which implies you don't actually know what the code under test will do. One of your tests may change the common product, possibly even put it in an invalid state. Your other tests will start to fail, making it tricky to figure out the source of the problem. Almost invariably, you want to start out using SetUp, which will create a separate product for each one of your tests.

Magnetometer answered 22/1, 2018 at 21:57 Comment(0)
B
4

The fixture setup for Moq seems reasonable to me.

However, reusing the same Product is suspect as it can be modified and accidentally reused which could lead to unstable tests. I would get a new Product each test run, that is if it's the system under test.

Brasca answered 22/1, 2018 at 19:10 Comment(2)
Thanks. Is Autofixture used to create mock objects only (I don't have any experience with it)? I am testing the core element of my app at the moment, which has no dependencies. Therefore I guess I should not be using Autofixture?Curtain
@Curtain i personally don't know.Brasca
B
1

Yes, you use OneTimeSetUp (and OneTimeTearDown) to do all the setup that will be shared among tests in that fixture. It is run once per test run, so regardless of however many tests in the fixture the code will execute once. Typically you will initialize instances held in private fields etc for the other tests to use, so that you don't end up with lots of duplicate setup code.

Blunderbuss answered 22/1, 2018 at 19:13 Comment(4)
Thanks. Is Autofixture used to create mock objects only (I don't have any experience with it)? I am testing the core element of my app at the moment, which has no dependencies. Therefore I guess I should not be using Autofixture?Curtain
@Curtain that would be best asked as a separate questionBlunderbuss
Fair enough. I have posted another question here: #48389361 if you would like to answer.Curtain
Say I wanted to build a list to be used in each method. Would I build the list in each test function (using the same ten lines of code in each test function) or create a Helper class for it? I am trying to use the principle of least astonishment as someone else will be looking at my code soon i.e. I cannot be lazy.Curtain

© 2022 - 2024 — McMap. All rights reserved.