如何在不将方法设为静态的情况下使用@Enclosed
how can I use @Enclosed without making methods as static
我需要不同的参数集,所以我决定使用 @Enclosed。但是,嵌套的 classes 必须是静态的,因此方法调用的所有现有 methods/constants 都必须是静态的。
但这很难,因为我无法更改所有这些方法的定义。
有没有什么方法可以使用@Enclosed而不用静态添加现有方法的定义?
这里有一个例子,这样你就知道我在问什么了。在这个例子中,由于 data() 是静态的,class someTest 必须是静态的,所以如果我调用 nonStaticMethod(),我在调用 nonStaticMethod() 的行得到 "Cannot make a static reference to the non-static method..."。
但我不想将 nonStaticMethod() 重新定义为静态。
@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
}
}
}
这是很多人都感到困惑的事情。 "static nested class" 的全部意思是内部 class 没有对外部 class 的引用。没有要求将方法或字段设为静态。
例如,查找 java.util.HashMap 的源代码,有一个名为 Entry 的静态内部 class 实现了 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
runner 要求封闭的 classes 是静态的(又名 "nested classes")。
编辑: 实际上,JUnit 永远不会实例化用 @RunWith(Enclosed.class)
注释的 class。使用 Enclosed
扩展另一个 class 的测试不会做任何事情,除非基础 class 具有用 JUnit 注释注释的字段或方法(@ClassRule
,@BeforeClass
等)。
我建议您通过委托共享代码,而不是继承。在您的情况下,您可以将 nonStaticMethod()
移动到不同的 class:
@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 中继承的一个常见问题是 class 只能有一个基数 class。但另一个问题是嵌套的 classes 无法访问外部 class 的状态,因此无法共享静态方法以外的代码。
编辑: 如果这不是一个选项,您的嵌套 classes 可以扩展您的基础 class:
@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 运行器:
@RunWith(JUnitParamsRunner.class)
public class MyParameterizedTest extends EnclosedBase {
@Parameters({"NY",
"CA" })
@Test
public void verifyStateTest(String state) {
nonStaticMethod();
}
}
我需要不同的参数集,所以我决定使用 @Enclosed。但是,嵌套的 classes 必须是静态的,因此方法调用的所有现有 methods/constants 都必须是静态的。 但这很难,因为我无法更改所有这些方法的定义。
有没有什么方法可以使用@Enclosed而不用静态添加现有方法的定义?
这里有一个例子,这样你就知道我在问什么了。在这个例子中,由于 data() 是静态的,class someTest 必须是静态的,所以如果我调用 nonStaticMethod(),我在调用 nonStaticMethod() 的行得到 "Cannot make a static reference to the non-static method..."。 但我不想将 nonStaticMethod() 重新定义为静态。
@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
}
}
}
这是很多人都感到困惑的事情。 "static nested class" 的全部意思是内部 class 没有对外部 class 的引用。没有要求将方法或字段设为静态。
例如,查找 java.util.HashMap 的源代码,有一个名为 Entry 的静态内部 class 实现了 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
runner 要求封闭的 classes 是静态的(又名 "nested classes")。
编辑: 实际上,JUnit 永远不会实例化用 @RunWith(Enclosed.class)
注释的 class。使用 Enclosed
扩展另一个 class 的测试不会做任何事情,除非基础 class 具有用 JUnit 注释注释的字段或方法(@ClassRule
,@BeforeClass
等)。
我建议您通过委托共享代码,而不是继承。在您的情况下,您可以将 nonStaticMethod()
移动到不同的 class:
@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 中继承的一个常见问题是 class 只能有一个基数 class。但另一个问题是嵌套的 classes 无法访问外部 class 的状态,因此无法共享静态方法以外的代码。
编辑: 如果这不是一个选项,您的嵌套 classes 可以扩展您的基础 class:
@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 运行器:
@RunWith(JUnitParamsRunner.class)
public class MyParameterizedTest extends EnclosedBase {
@Parameters({"NY",
"CA" })
@Test
public void verifyStateTest(String state) {
nonStaticMethod();
}
}