如何在多个测试项目中 运行 只使用一次单例方法

How to run singleton method only once in multiple test projects

我有三个测试项目。所有这些都引用自模型项目:

我在模型项目中创建了 TestBase class 并将其用作所有测试 class 的基础 class。 继承看起来像这样:

[TestClass]
    public class UnitTest1 : TestBase
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }

在 TestBase 中我有 TestInitialize:

 [TestInitialize]
        public void Initialize()
        {
            SingletonClass.Initiate();
        }

        [TestCleanup]
        public void Cleanup()
        {
            //Do some
        }

SingletonClass 是测试中需要的静态 class。我需要启动一次,所以我这样做了:

public static class SingletonClass
    {
        public static bool IsInitiated { get; set; }

        public static void Initiate()
        {
            if (!IsInitiated)
            {
                IsInitiated = true;
                //Do some
                Thread.Sleep(5000);
            }
        }
    }

当我 运行 测试一个项目时它工作正常,但是当我 运行 全部启动它时它启动了 3 次(耗时 15 秒)。当我 运行 所有测试时,有什么办法只 运行 它一次吗?

类 能够拥有一个仅在首次引用 class 时调用的构造函数。

public static class SingletonClass
    {
        static SingletonClass()
        {
             IsInitiated = true;
             //Do some
             Thread.Sleep(5000);
        }
    }

根据您的测试运行器,您可能会为每个测试项目获得一个新流程。因此,单例确实被实例化了三次,每个进程一次。

您可以通过告诉 nunit 只对所有项目使用一个进程来解决这个问题:

 nunit3-console.exe MyProject.dll --agents=1

编辑:对于 vstest,您可以设置 MaxCpuCount 参数。有关详细信息,请参阅 docs

<MaxCpuCount>1</MaxCpuCount>

您在 3 个并行使用者之间存在共享状态问题。您无法像 Ben 解释的那样控制 vstests 如何创建进程。

执行此操作的唯一方法是将 SingletonClass 初始化移动到它自己的进程中,并让其他 3 个测试项目与该单独的进程通信。这将确保它只发生一次,无论 vstest 创建了多少个进程。

当然,只有在初始化非常昂贵的情况下才值得这样做。

通常您应该避免在测试之间共享状态。它使它们变脆。

恕我直言,每个测试都应定义使用的资源。这样,先前的测试就不会破坏当前的测试。但是如果你想要这种情况发生,你可以使用单例模式。喜欢:

public class MyClass
{
    private static readonly MyClass _myClass = new MyClass();

    private MyClass()
    {
        // Initialize your class here
    }

    public static MyClass Instance
    {
        get => _myClass;
    }
}

静态值应该在多个单元测试中保持有效。

终于找到了解决办法。我使用 ILRepack 将所有项目合并到一个新项目 (AllTests) 中:

 <!-- ILRepack -->
  <Target Name="ILRepack" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
    <PropertyGroup>
      <WorkingDirectory>$(OutputPath)</WorkingDirectory>
    </PropertyGroup>
    <ItemGroup>
      <InputAssemblies Include="$(OutputPath)MainTest.dll" />
      <InputAssemblies Include="$(OutputPath)FIrst.dll" />
      <InputAssemblies Include="$(OutputPath)Second.dll" />
      <InputAssemblies Include="$(OutputPath)Third.dll" />
    </ItemGroup>
    <Message Text="MERGING: @(InputAssemblies->'%(Filename)') into $(OutputAssembly)" Importance="High" />
    <ILRepack OutputType="$(OutputType)"  Internalize="false" MainAssembly="$(AssemblyName).dll" OutputAssembly="$(AssemblyName).dll" InputAssemblies="@(InputAssemblies)" WorkingDirectory="$(WorkingDirectory)" />
  </Target>
  <!-- /ILRepack -->

现在,我可以 运行 所有测试都使用 vstest.console.exe:

vstest.console.exe AllTests.dll

或者我可以 运行 来自 visual studio:

单身人士class 只按时启动。我不知道它是如何产生负面影响的,但目前它运行良好