C# 如何在 xUnit.net 测试中只运行一次设置代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12379949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:04:22  来源:igfitidea点击:

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

c#asp.netxunitxunit.net

提问by Chris

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.

我正在尝试使用 Xunit 设置我的测试。我需要删除测试开始文件夹中的所有图像,然后每种方法都会调整一些图像大小并将其输出的副本保存到文件夹中。文件夹应该只清空一次,然后每种方法都会将自己的图像保存到文件夹中。

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

当我使用 时IUseFixture<T>,该ClearVisualTestResultFolder函数仍在每次测试之前被调用,所以我最终在文件夹中只有一个图像。

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 ClearVisualTestResultFolderin 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?

如果我把 放在ClearVisualTestResultFolder构造函数中,它也会为每个测试方法调用一次。我只需要在执行所有测试方法之前运行一次,我该如何实现?

If it matters, I use the ReSharper test runner.

如果重要,我会使用 ReSharper 测试运行器。

采纳答案by nithins

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:

按照此xUnit 讨论主题中的指导,您似乎需要在 Fixture 上实现构造函数并实现 IDisposable。这是一个完整的示例,它的行为符合您的要求:

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

D:\xUnit>xunit.console.clr4.exe test.dll /html foo.htm xUnit.net 控制台测试运行程序(64 位 .NET 4.0.30319.17929) 版权所有 (C) 2007-11 Microsoft Corporation。

xunit.dll:版本 1.9.1.1600 测试程序集:test.dll

SomeFixture ctor:这应该只运行一次

测试完成:2 个,共 2 个

SomeFixture:处置 SomeFixture

总共 2 个,0 个失败,0 个跳过,耗时 0.686 秒

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

然后,当你破解打开测试输出文件 foo.htm 时,你会看到另一个测试输出。

回答by Ruben Bartelink

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

IUseFixture<T>.SetFixture每次测试都会调用一次。Fixture 本身只创建一次。

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

换句话说,您不应该在 SetFixture 方法中执行任何操作,而应该在 Fixture 构造函数中触发它。

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

对于一次性清理,IDisposable.Dispose在 Fixture 上实现一个(虽然不是必需的)

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

请注意,在测试之间(甚至可能)共享状态是一个坏主意。最好使用TemporaryDirectoryFixture像这样的

回答by CodeZila

The old IUseFixture<T>interface in xUnit.net v1.xhas 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.

xUnit.net v1.x 中的旧IUseFixture<T>接口已被两个新接口取代:和. 此外,将夹具值注入测试的机制已从属性设置器更改为构造函数参数。类夹具创建一次并在同一类中的所有测试之间共享(很像旧的 IUseFixture)。集合装置以相同的方式工作,除了单个实例在同一测试集合中的所有测试之间共享。IClassFixture<T>ICollectionFixture<T>