有一种方法可以在同时运行多个测试时模仿单元测试用例中的startup.cs的功能?

时间:2020-08-25 13:34:17

标签: c# .net-core xunit

我正在尝试测试一些使用静态类的代码。静态类具有一个初始化方法,该方法只能调用一次,如果第二次调用,则引发异常。我有多个测试用例,用于测试需要访问静态类的代码。在代码中,初始化是在startup.cs中完成的。如何为测试用例做类似的事情。我正在使用x-unit进行单元测试。

 public static class UniqueId
{
    public static void Initialize()
    {
        if (_generator != null)
            throw new Exception("Already initialized.");
        _generator = new IdGenerator();
    }


    private static IdGenerator _generator = null;
    
    public static BigId NextId()
    {
        if (_generator == null)
            throw new Exception("Not initialized.");
        return _generator.NextId();
    }
}

我要测试的代码:

public string GenerateId
{
    return UniqueId.NextId().ToString()
}

3 个答案:

答案 0 :(得分:0)

在特定情况下,您需要设置您的类以实现IDisposible,并在要销毁它时调用Dispose()。

这里有个例子:

namespace Prime.UnitTests.Services
{
    [TestFixture]
    public class YourClassTest
    {

        [SetUp]
        public void SetUp()
        {
            //some configs...
        }

        [Test]
        public void Test_size_String_1()
        {
            UniqueId.Initialize();
            Assert.IsFalse(UniqueId.NextId().ToString() == 10); // quick example...
            UniqueId.Dispose();
        }

        [Test]
        public void Test_size_String_2XPTO()
        {
            UniqueId.Initialize();
            Assert.IsFalse(UniqueId.NextId().ToString() == 115); // quick example...
            UniqueId.Dispose();
        }

    }
}


public static class UniqueId : IDisposable  
{
    public static void Initialize()
    {
        if (_generator != null)
            throw new Exception("Already initialized.");
        _generator = new IdGenerator();
    }


    private static IdGenerator _generator = null;
    
    public static BigId NextId()
    {
        if (_generator == null)
            throw new Exception("Not initialized.");
        return c.NextId();
    }

    public void Dispose()
    {
        _generator?.Dispose(); //Depends of the context of your IdGenerator
        //or
        _generator == null;
    }
}

答案 1 :(得分:0)

假设我了解了MSTest中的[TestInitialize][ClassInitialize](可能是您需要的内容),并查看它们是否都适合您的“启动”功能用例

[TestInitialize]

  • 在所有单元测试(每个单元测试)之前运行

[ClassInitialize]

  • 运行一次,这几天我能找到的唯一官方文档更旧...

ClassInitializeAttribute类

标识包含以下任何代码之前必须使用的代码的方法 测试类中的测试已经运行并分配了资源 由测试类使用。此类不能继承。

备注

在负载测试中运行时,使用此属性标记的方法 将运行一次,并且它执行的任何初始化操作都将 适用于整个测试。如果需要进行初始化操作 对于测试中的每个虚拟用户迭代,请使用一次 TestInitializeAttribute。

方法将运行的顺序为:

  1. 标记为AssemblyInitializeAttribute的方法。

  2. 标记为ClassInitializeAttribute的方法。

  3. 标记为TestInitializeAttribute的方法。

  4. 标记为TestMethodAttribute的方法。

只有一个类中的一个方法可以用此属性修饰。

重要

此属性不应在ASP.NET单元测试中使用,即任何 使用[HostType(“ ASP.NET”)]属性进行测试。因为无国籍 IIS和ASP.NET的本质,用此属性修饰的方法可能 在每次测试运行中被多次调用。

高度

答案 2 :(得分:-2)

这取决于您使用的测试框架。

编辑:我现在看到您使用的是xUnit,但我会保留整个答案,以防对他人有所帮助。

xUnit

您可以选中this answer,其中讨论了如何为一组测试创建全局设置/拆卸。总结一下答案,如果您在Xunit中为单元测试类创建一个构造函数,则该方法将在每个测试方法之前调用。它还指出:

更优化的版本将使用IClassFixture接口来 确保仅全局初始化/拆卸功能 打电话一次。对于此版本,您不会从 您的测试类,但实现IClassFixture接口,其中T 指的是您的设备类别:

using Xunit;

public class TestsFixture : IDisposable {
    public TestsFixture ()
    {
        // Do "global" initialization here; Only called once.
    }

    public void Dispose()
    {
        // Do "global" teardown here; Only called once.
    } }

public class DummyTests : IClassFixture<TestsFixture> {
    public DummyTests(TestsFixture data)
    {
    }
} 

这将导致仅运行TestsFixture的构造函数 每个测试班一次。因此,这取决于您想要什么 完全可以在两种方法之间进行选择。

如果您使用的是 NUnit ,则它已经具有OneTimeSetUp属性,您可以使用(docs here),如下所示:

[TestFixture]
public class MyTestFixture
{
    [OneTimeSetUp]
    public void OneTimeSetUp()
    {
        // Initialize things here; only called once
    }
}

如果您使用的不是xUnit和NUnit,请查看所用框架的文档,并查找一次性设置。