我需要不同的参数集,所以我决定使用@Enclosed。但是,嵌套类必须是静态的,因此方法调用的所有现有方法/常量都必须是静态。但这很难,因为我无法改变所有这些方法的定义。
有没有办法在不添加带有static的现有方法的定义的情况下使用@Enclosed?
这里有一个例子,让你知道我在问什么。在本例中,由于data((是静态的,类someTest必须是静态的。因此,如果我调用nonStaticMethod((,我在调用nonStatic method((的行中得到"Cannot make a static reference to the non-static method…"。但我不想将nonStaticMethod((重新定义为static。
@RunWith(Enclosed.class)
public class EnclosedParameterizedTest extends EnclosedBase{
@RunWith(Parameterized.class)
public static class SomeTest {
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
new Object[]{"NY"},
new Object[]{"CA"},
});
}
String state;
public SomeTest(String state) {
this.state = state;
}
@Test
public void verifyStateTest(){
nonStaticMethod(); //a method already defined in parent of
//EnclosedBase which I cannot re-define
}
}
}
很多人对此感到困惑。"静态嵌套类"的全部含义是内部类没有对外部类的引用。没有要求方法或字段是静态的。
举个例子,查找java.util.HashMap的源代码,有一个名为Entry的静态内部类实现java.util.Map.Entry
:
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
// ...
显然,映射必须有多个条目,因此static
关键字不会用于指示这是某种单例。
不幸的是,Enclosed
运行程序要求封闭的类是静态的(也称为"嵌套类"(。
编辑:事实上,JUnit永远不会实例化用@RunWith(Enclosed.class)
注释的类。让一个使用Enclosed
的测试扩展另一个类不会有任何作用,除非基类有用JUnit注释(@ClassRule
、@BeforeClass
等(注释的字段或方法。
我建议您通过委派共享代码,而不是继承。在您的情况下,您可以将nonStaticMethod()
移动到另一个类:
@RunWith(Enclosed.class)
public class EnclosedParameterizedTest {
@RunWith(Parameterized.class)
public static class SomeTest {
public final Helper helper = new Helper();
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
new Object[] { "NY" },
new Object[] { "CA" },
});
}
String state;
public SomeTest(String state) {
this.state = state;
}
@Test
public void verifyStateTest(){
helper.nonStaticMethod();
}
}
}
一般来说,委派比继承更灵活。Java中继承的一个常见问题是,一个类只能有一个基类。但另一个问题是,嵌套类不能访问外部类的状态,因此不能共享静态方法以外的代码。
编辑:如果这不是一个选项,你的嵌套类可以扩展你的基类:
@RunWith(Enclosed.class)
public class EnclosedParameterizedTest {
@RunWith(Parameterized.class)
public static class SomeTest extends EnclosedBase {
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
new Object[] { "NY" },
new Object[] { "CA" },
});
}
String state;
public SomeTest(String state) {
this.state = state;
}
@Test
public void verifyStateTest(){
nonStaticMethod();
}
}
}
或者,如果您想要不同测试的不同参数集,可以考虑使用JUnitParams runner:
@RunWith(JUnitParamsRunner.class)
public class MyParameterizedTest extends EnclosedBase {
@Parameters({"NY",
"CA" })
@Test
public void verifyStateTest(String state) {
nonStaticMethod();
}
}