我正在尝试运行一个参数化的junit测试,其中的参数在测试中必须是常量,所以我使用反射来设置该参数。然而,它并不是很有效。在下面的示例中,它总是打印Testing with: param-1。我该如何解决这个问题?令人惊讶的是,我在调试器中为不同的运行实例获得了正确的PARAM_NAME (参数-1,参数-2,参数-2)值,但它在控制台上总是打印为"param-1“,并且在测试中也用作"param-1”。这可以通过以下事实部分解释:注释是在编译时计算的,因此注释中的值在运行时不能更改?
@RunWith(Parameterized.class)
public class SomeTest {
private final String PARAM_NAME = "param-1";
public SomeTest(String someParam){
org.springframework.test.util.ReflectionTestUtils.setField(this, "PARAM_NAME", someParam);
}
@Parameterized.Parameters
public static Collection parameters() {
return Arrays.asList(new Object[][] {
{ "param-1" },
{ "param-2" },
{ "param-3" }
});
}
@Test
@ExternalAnnotation(PARAM_NAME) //needs constant in annotation
public void testSomething() throws Exception {
System.out.println("Testing with: "+PARAM_NAME); //always prints param-1
//some tests
}
}发布于 2017-11-10 07:15:35
注释值由JVM缓存,您无法在运行时对其进行更改。我能想到的实现目标的唯一可能方法是通过源代码生成(基于模板,或者使用像JCodeModel这样的库)以编程方式生成测试类。如果您在测试编译之前的生命周期阶段这样做(假设您使用的是Maven或Gradle之类的构建系统),那么您应该可以相对轻松地启动和运行。
发布于 2017-11-10 11:37:14
我可以通过在运行时更改注释值来实现:
public static void changeAnnotationValue(Annotation annotation, String key, Object newValue) throws NoSuchFieldException, IllegalAccessException {
Object handler = Proxy.getInvocationHandler(annotation);
Field f = handler.getClass().getDeclaredField("memberValues");
f.setAccessible(true);
Map<String, Object> memberValues = (Map<String, Object>) f.get(handler);
memberValues.put(key,newValue);
}我将通过以下方式调用此方法:
public SomeTest(String someParam){ changeAnnotationValue(SomeTest.class.getMethod("testSomething").getAnnotation(ExternalAnnotation.class), "value", someParam);}虽然在主代码中这样做是完全不可取的,但这可能会有副作用。我只是在一个测试类中这样做。
https://stackoverflow.com/questions/47195465
复制相似问题