我正在使用jUnit来管理访问数据库的应用程序的集成测试。因为设置测试数据是一项耗时的操作,所以我一直在@BeforeClass
方法中这样做,每个测试类只执行一次(而不是运行的@Before
方法)每种测试方法一次。)
现在我想尝试一些不同的排列来配置数据层,在每个不同的配置上运行我的所有测试。这似乎是Parameterized
测试运行器的自然使用。问题是,Parameterized
为类构造函数提供参数,@BeforeClass
方法是抽象的,并在类构造函数之前调用。
几个问题,
Parameterized
是否为每个参数排列调用@BeforeClass
方法,还是只调用一次?
如果重复调用@BeforeClass
方法,是否有某种方法可以从内部访问参数值?
如果没有这些,人们认为什么是解决这个问题的最佳替代方法?
答案 0 :(得分:3)
我认为你需要一个自定义测试运行器。我遇到了同样的问题(需要使用多个昂贵的配置运行相同的测试)。您需要一种方法来参数化设置,可能使用类似于参数化运行器使用的@Parameter注释,但是使用静态成员字段而不是实例字段。自定义运行器必须使用@Parameter注释查找所有静态成员字段,然后每个静态@Parameter字段运行一次测试类(可能使用基本的BlockJunit4ClassRunner)。 @Parameter字段应该是@ClassRule。
Andy on Software在开发自定义测试运行器方面做得很好,他在这些博文here和here中非常清楚地解释了这一点。
答案 1 :(得分:1)
@BeforeClass仅在您的示例中调用一次。考虑到这个名字,这在课前是有道理的!
如果你的测试需要不同的数据,我可以想到两个选择:
答案 2 :(得分:0)
您可以在测试类的构造函数中调用此初始化逻辑。跟踪静态变量中使用的最后一个参数。更改时,请为新参数设置类。
我想不出AfterClass的等价物。
答案 3 :(得分:0)
这是一个老问题,但我只需解决一个可能类似的问题。我现在使用下面的解决方案,这实际上是使用通用抽象基类的TREE(更新)答案的实现,以便在需要此机制时避免重复。
具体测试将提供一个@Parameters方法,该方法返回包含Supplier< T>每。然后,根据具体测试方法所需的实际输入,这些供应商只执行一次。
@RunWith(Parameterized.class)
public class AbstractBufferedInputTest<T> {
private static Object INPUT_BUFFER;
private static Object PROVIDER_OF_BUFFERED_INPUT;
private T currentInput;
@SuppressWarnings("unchecked")
public AbstractBufferedInputTest(Supplier<T> inputSuppler) {
if (PROVIDER_OF_BUFFERED_INPUT != inputSuppler) {
INPUT_BUFFER = inputSuppler.get();
PROVIDER_OF_BUFFERED_INPUT = inputSuppler;
}
currentInput = (T) INPUT_BUFFER;
}
/**
*
* @return the input to be used by test methods
*/
public T getCurrentInput() {
return currentInput;
}
}
答案 4 :(得分:-1)
您可以在@Before方法中进行初始化,写入实例变量但测试为null。
@RunWith(value = Parameterized.class)
public class BigThingTests {
private BigThing bigThing;
@Before
public void createBitThing() {
if (bigThing == null) {
bigThing = new BigThing();
}
}
...
}
为每组参数创建BigThingTests
的新实例,并为每个新实例将bigThing
设置为null。 Parameterized
运行器是单线程的,因此您不必担心多次初始化。