简体   繁体   English

如何在多个测试项目中只运行一次 singleton 方法

[英]How to run singleton method only once in multiple test projects

I have three test projects.我有三个测试项目。 All of them referenced from the Model project:所有这些都引用自 Model 项目:

项目

I created the TestBase class in the Model project and using it as the base class of all test classes.我在 Model 项目中创建了 TestBase class,并将其用作所有测试类的基础 class。 Inheritance looks like this: Inheritance 看起来像这样:

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

In TestBase I have TestInitialize:在 TestBase 我有 TestInitialize:

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

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

SingletonClass is a static class that needs in tests. SingletonClass 是需要测试的 static class。 I need to initiate it once so I am doing this:我需要启动一次,所以我这样做:

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

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

It is working fine when I run tests of one project, but when I run all it is initiating it 3 times(took 15 seconds).当我运行一个项目的测试时它工作正常,但是当我运行所有它时它启动它 3 次(花了 15 秒)。 Is there any way to run it only once when I run all tests?当我运行所有测试时,有没有办法只运行一次?

Depending on your test-runner you may get a new process for every test-project.根据您的测试运行者,您可能会为每个测试项目获得一个新流程。 Therefor the singleton is indeed instantiated three times, once per process.因此 singleton 确实被实例化了三次,每个进程一次。

You can solve that by telling nunit to only use a single process for all projects:你可以通过告诉 nunit 对所有项目只使用一个进程来解决这个问题:

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

EDIT: For vstest you can set the MaxCpuCount -parameter.编辑:对于 vstest,您可以设置MaxCpuCount参数。 See the docs for further details:有关更多详细信息,请参阅文档

<MaxCpuCount>1</MaxCpuCount>

Finally, I found a solution.最后,我找到了解决方案。 I merged all projects into a new project (AllTests) using ILRepack:我使用 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 -->

Now, I can run all tests using vstest.console.exe:现在,我可以使用 vstest.console.exe 运行所有测试:

vstest.console.exe AllTests.dll

Or I can run it from the visual studio:或者我可以从视觉工作室运行它:

从 vs 运行测试

Singleton class initiating only on time. Singleton class 仅准时启动。 I don't know how it affects negatively, but currently, it is working fine我不知道它如何产生负面影响,但目前,它工作正常

You have a shared state problem between 3 parallel consumers.您在 3 个并行消费者之间有一个共享的 state 问题。 You don't control how vstests creates processes like Ben explained.您无法控制 vstests 如何创建 Ben 解释的流程。

The only way to do this is to move the SingletonClass initialization in its own process and have the other 3 Test projects communicate with that separate process.这样做的唯一方法是将 SingletonClass 初始化移动到它自己的进程中,并让其他 3 个测试项目与该单独的进程进行通信。 That will make sure it only happens once no matter how many processes are created by vstest.这将确保它只发生一次,无论 vstest 创建了多少进程。

Of course, that's only worth doing if that initialization is really expensive.当然,只有在初始化非常昂贵的情况下才值得这样做。

Generally you should avoid shared state between Tests.通常,您应该避免在测试之间共享 state。 It makes them brittle.它使它们变脆。

Imho used resources should be defined per test.恕我直言,应根据测试定义使用的资源。 That way a previous test can't botch up the current test.这样,以前的测试就不会搞砸当前的测试。 But if you want this to happen, you can make use of the Singleton pattern.但是,如果您希望这种情况发生,您可以使用 Singleton 模式。 Like:喜欢:

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

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

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

Static values should be kept alive over multiple unit tests. Static 值应在多个单元测试中保持有效。

Classes have the ability to have a constructor that is called only when the class is first referenced.类能够拥有一个仅在首次引用 class 时才调用的构造函数。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM