Sharing services across test classes in MSTest
我正在 MSTest 中进行大量集成测试(一个子系统为 100 个),我真的想将相关测试分组到他们自己的测试类中,以提高可读性,因为不同的测试组需要不同的配置设置。
测试最初是从一个包含某些服务的静态实例的大型测试类开始的。这些服务需要一段时间才能启动,如果每次测试都启动和拆除它们,它们将主导测试执行时间。原来的测试代码是这样开始的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | [TestClass] public class IntegrationTests { static ServiceA serviceA = new ServiceA(); static ServiceB serviceB = new ServiceB(); [ClassInitialize] public static void ClassInit(TestContext context) { /* Gets the services up and going */ } [TestInitialize] public void TestInit() { /* Gets services back into good states */ } /* Lots and lots of Integration tests */ [ClassCleanup] public static void ClassCleanup() { /* Tear down the services */ } } |
问题在于不同的测试组需要在测试运行之前将服务置于不同的状态。
我的第一个想法是将静态服务保留在一个通用的基类测试类中,然后为每个测试组创建从基类继承的新测试类,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [TestClass] public class TestClassA : IntegrationTests { /* tests */ } [TestClass] public class TestClassB : IntegrationTests { /* tests */ } [TestClass] public class TestClassC : IntegrationTests { /* tests */ } |
问题在于每个测试类的服务都会被启动和拆除。当然,这并不像为每个单独的测试创建和销毁它们那么糟糕,但我想为每次测试运行创建一次。
有没有办法让单独的测试类共享相同的服务以在 MSTest 中进行集成测试?
如果我正确理解您的问题,您可以使用单独的单例实现这些服务。类似于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class Services { static ServiceA _serviceA static ServiceB _serviceB public static ServiceA InstanceA { if (_serviceA == null) _serviceA = new ServiceA(); return _serviceA; } public static ServiceB InstanceB { if (_serviceB == null) _serviceB = new ServiceB(); return _serviceB; } } |
那么这个类可以被你所有的测试类共享。
IProgrammer 的答案会起作用,但这是我想出的解决方案。
我在启动所有服务的基础测试类中添加了一个静态构造函数,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [TestClass] public class IntegrationTests { static ServiceA serviceA = new ServiceA(); static ServiceB serviceB = new ServiceB(); //Static constructor gets called once during the lifetime of the appdomain. static IntegrationTests() { /* Gets the services up and going */ } [TestInitialize] public void TestInit() { /* Gets services back into good states */ } /* Lots and lots of Integration tests */ } |
在所有测试运行后清理资源有点棘手,因为 C# 没有静态析构函数。
但是,这个答案提供了一个相当干净和聪明的解决方法。
这是"静态"析构函数代码。
1 2 3 4 5 6 7 8 | private static readonly Destructor Finalise = new Destructor(); private sealed class Destructor { ~Destructor() { /* Service cleanup code here */ } } |