我正在MSTest进行大量的集成测试(100+用于子系统),我真的想将相关的测试分组到他们自己的测试类中,以提高可读性,因为不同的测试组需要不同的配置设置。
测试最初是从一个大的测试类开始的,它包含某些服务的静态实例。这些服务需要一段时间才能启动,并且如果它们在每个测试中被提起并拆除,它们将主导测试执行时间。原始测试代码就是这样开始的。
[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 */
}
}
问题在于,不同的测试组需要在运行测试之前将服务放入不同的状态。
我的第一个想法是将静态服务保存在一个公共基础测试类中,然后创建从每个测试组的基类继承的新测试类,如下所示:
[TestClass]
public class TestClassA : IntegrationTests
{
/* tests */
}
[TestClass]
public class TestClassB : IntegrationTests
{
/* tests */
}
[TestClass]
public class TestClassC : IntegrationTests
{
/* tests */
}
问题在于每个测试类的服务都会被刷新并拆除。当然,这并不像为每个单独的测试创建和销毁它们那么糟糕,但我想为每次测试运行创建一次。
有没有办法让单独的测试类在MSTest中共享相同的服务进行集成测试?
答案 0 :(得分:1)
如果我正确理解您的问题,您可以使用单独的单例来实现这些服务。类似的东西:
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;
}
}
然后,所有测试类都可以共享此类。
答案 1 :(得分:0)
IProgrammer的回答将起作用,但这是我提出的解决方案。
我在基础测试类中添加了一个静态构造函数,其中所有服务都是旋转的,如下所示:
[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#没有静态析构函数。
然而,this answer provided是一个相当干净和聪明的解决方法。
这是“静态”析构函数代码。
private static readonly Destructor Finalise = new Destructor();
private sealed class Destructor
{
~Destructor()
{
/* Service cleanup code here */
}
}