让我们假设以下JUnit测试类:
@RunWith(Parameterized.class)
public class MyTestClass {
private ExpensiveObjectToCreate myObject;
@Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
@Test
public void test1() {
}
@Test
public void test2() {
}
public MyTestClass(String stringParameter) {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
}
我有什么方法可以为每个参数集创建一次昂贵的对象吗?我这样说是因为JUnit为每个需要运行的测试创建了一个新的测试类。这意味着昂贵的对象不会被创建2次,但实际上是4次(2个参数集x 2次测试)。当我们有许多测试方法时,这会变得更糟。
另外,将昂贵的对象作为参数发送对我来说不是解决方案,因为我的场景有点复杂(我在JUnit规则中创建了昂贵的对象)。
答案 0 :(得分:2)
为什么不在测试用例类中推出自定义cacher,它会缓存每个参数创建的实例,并在进一步调用时返回相同的实例。
@RunWith(Parameterized.class)
public class Test {
private static ExpensiveObjectCacher cacher; //instance which caches parameter instance
private ExpensiveObject myObject;
public Test(String value) {
this.myObject = cacher.get(value);
}
@BeforeClass
public static void setUpBeforeClass(){
cacher = new ExpensiveObjectCacher();
}
@Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
@org.junit.Test
public void test1(){
}
@org.junit.Test
public void test2(){
}
}
//caching for test cases.
class ExpensiveObjectCacher{
private Map<String, ExpensiveObject> map = new ConcurrentHashMap<String, ExpensiveObject>();
ExpensiveObject get(String value){
ExpensiveObject instance = map.get(value);
if(instance == null){
instance = new ExpensiveObject(value);
map.put(value, instance);
}
return instance;
}
}
class ExpensiveObject{
public ExpensiveObject(String value) {
System.out.println("Instance created: " + value);
}
}
Instance created: parameter1
Instance created: parameter2
答案 1 :(得分:2)
您可以使用参数(此处为简单字符串)中的静态Map
到ExpensiveObjectToCreate
的实例。
@RunWith(Parameterized.class)
public fnial class MyTestClass {
private static final Map<Parameter, ExpensiveObjectToCreate> MAPPING = new HashMap<>();
private ExpensiveObjectToCreate myEOTC;
public MyTestClass(String stringParameter) {
myEOTC = getEOTC(new Parameter(stringParameter));
}
private static getEOTC(Parameter parameter) {
ExpensiveObjectToCreate eotc = MAPPING.get(parameter);
if (eotc == null) {
eotc = new ExpensiveObjectToCreate(parameter.stringParameter);
MAPPING.put(parameter, eotc);
}
rturn eotc;
}
private static final class Parameter {
String stringParameter;
Parameter(String stringParameter) { this.stringParameter = stringParameter; }
@Override public int hashCode() { ... }
@Override public boolean equals(Object other) { ... }
}
}
但是,如果您还需要限制昂贵对象的数量,则应该做更多的工作,例如缓存可能是一种解决方案。
答案 2 :(得分:1)
如果您使用的是Junit 4:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
@BeforeClass
public static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
如果是Junit 3:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
@BeforeClass
protected static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
在这两种情况下,对象都将为所有单元测试创建一次。
编辑:字符串我不知道它来自何处,所以我认为所有单元测试的字符串都相同。