How to run setup code only once in an xUnit.net test

放肆的年华 提交于 2019-12-20 16:54:06

问题


I'm trying to setup my tests using Xunit. I have a requirement to delete all images in a folder start of the tests, and then each method does some image resizing and saves a copy of it's output to the folder. The folder should only be emptied once, and then each method will save their own image into the folder.

When I use IUseFixture<T>, the ClearVisualTestResultFolder function is still being called before every test, so I only end up with one image in the folder.

public class Fixture
{
    public void Setup()
    {
        ImageHelperTest.ClearVisualTestResultFolder();
    }
}

public class ImageHelperTest : IUseFixture<EngDev.Test.Fixture>
{
    public void SetFixture(EngDev.Test.Fixture data)
    {
        data.Setup();
    }

    public static void ClearVisualTestResultFolder()
    {
        // Logic to clear folder
    }
}

If I put the ClearVisualTestResultFolder in the constructor, it is also being called once for every test method. I need this just run once before all test methods are executed, how can I achieve this?

If it matters, I use the ReSharper test runner.


回答1:


Following the guidance in this xUnit discussion topic, it looks like you need to implement a constructor on the Fixture and also implement IDisposable. Here's a complete sample that behaves the way you want:

using System;
using System.Diagnostics;
using Xunit;
using Xunit.Sdk;

namespace xUnitSample
{
    public class SomeFixture : IDisposable
    {
        public SomeFixture()
        {
            Console.WriteLine("SomeFixture ctor: This should only be run once");
        }

        public void SomeMethod()
        {
            Console.WriteLine("SomeFixture::SomeMethod()");
        }

        public void Dispose()
        {
            Console.WriteLine("SomeFixture: Disposing SomeFixture");
        }
    }

    public class TestSample : IUseFixture<SomeFixture>, IDisposable
    {
        public void SetFixture(SomeFixture data)
        {
            Console.WriteLine("TestSample::SetFixture(): Calling SomeMethod");
            data.SomeMethod();
        }

        public TestSample()
        {
            Console.WriteLine("This should be run once before every test " + DateTime.Now.Ticks);
        }

        [Fact]
        public void Test1()
        {
            Console.WriteLine("This is test one.");
        }

        [Fact]
        public void Test2()
        {
            Console.WriteLine("This is test two.");
        }

        public void Dispose()
        {
            Console.WriteLine("Disposing");
        }
    }
}

When running this from the console runner, you'll see the following output:

D:\xUnit>xunit.console.clr4.exe test.dll /html foo.htm xUnit.net console test runner (64-bit .NET 4.0.30319.17929) Copyright (C) 2007-11 Microsoft Corporation.

xunit.dll: Version 1.9.1.1600 Test assembly: test.dll

SomeFixture ctor: This should only be run once

Tests complete: 2 of 2

SomeFixture: Disposing SomeFixture

2 total, 0 failed, 0 skipped, took 0.686 seconds

Then, when you crack open the test output file foo.htm, you'll see the other test output.




回答2:


The old IUseFixture<T> interface in xUnit.net v1.x has been replaced by two new interfaces: IClassFixture<T> and ICollectionFixture<T>. In addition, the mechanism for injecting fixture values into your tests has changed from property setters to constructor arguments. Class fixtures are created once and shared amongst all tests in the same class (much like the old IUseFixture). Collection fixtures work the same way, except that the single instance is shared amongst all tests in the same test collection.




回答3:


IUseFixture<T>.SetFixture gets called once for each test. The Fixture itself is only created once.

In other words, you shouldnt be doing anything in your SetFixture method, but you should be instead be triggering it in the Fixture constructor.

For one-time cleanup, implement an IDisposable.Dispose on the Fixture (it's not required though)

Note that it's a bad idea to be (even potentially) sharing state between tests. Best to use a TemporaryDirectoryFixture like this one.



来源:https://stackoverflow.com/questions/12379949/how-to-run-setup-code-only-once-in-an-xunit-net-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!