由于 public 私有字段悖论,无法使用 Junit @Rule 进行 CdiUnit 测试
CdiUnit test with Junit @Rule is impossible because of a public private field paradox
以下代码片段足以重现我的问题:
- 要么我设置了
thrown
属性 public
并得到错误 org.jboss.weld.exceptions.DefinitionException: WELD-000075: Normal scoped managed bean implementation class has a public field
- 或者我删除
public
修饰符并得到错误 org.junit.internal.runners.rules.ValidationError: The @Rule 'thrown' must be public.
- 我还尝试让
public
修饰符就位并在 class 上添加 @Dependent
注释范围,但出现错误 org.jboss.weld.exceptions.DefinitionException: WELD-000046: At most one scope may be specified on [EnhancedAnnotatedTypeImpl] public @Dependent @ApplicationScoped @RunWith
我删除了所有不必要的代码,但这是一个相当复杂的单元测试,带有模拟、通过 CDI 进行服务注入以及一些预计会引发异常的测试方法。
import org.jglue.cdiunit.CdiRunner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(CdiRunner.class)
public class FooBarTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void test() {
}
}
所以我的问题是,一方面 Weld 希望所有字段都不是 public,否则它将无法代理 class,另一方面,JUnit 想要 Rule字段是 public 因为它使用反射来访问它们并且不想使用 setAccessible(true)
方法,因为在安全管理器处于活动状态的情况下。如何处理这个悖论?
注意:我还发现了 this answer 的提示评论,指出
You can also annotate a method with @Rule, so this would avoid the problem
但是我找不到任何在方法上带有 @Rule
注释的 junit 测试示例,我打算就此提出一个单独的问题。
我找到了解决问题的方法。为了将来参考,这里有一个有效的片段,希望这对其他人有帮助。
import org.jglue.cdiunit.CdiRunner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(CdiRunner.class)
public class FooBarTest {
private ExpectedException thrown = ExpectedException.none();
@Rule
public ExpectedException getThrown() {
return thrown;
}
@Test
public void test() {
thrown.expect(ArithmeticException.class);
int i = 1 / 0;
}
}
以下代码片段足以重现我的问题:
- 要么我设置了
thrown
属性public
并得到错误org.jboss.weld.exceptions.DefinitionException: WELD-000075: Normal scoped managed bean implementation class has a public field
- 或者我删除
public
修饰符并得到错误org.junit.internal.runners.rules.ValidationError: The @Rule 'thrown' must be public.
- 我还尝试让
public
修饰符就位并在 class 上添加@Dependent
注释范围,但出现错误org.jboss.weld.exceptions.DefinitionException: WELD-000046: At most one scope may be specified on [EnhancedAnnotatedTypeImpl] public @Dependent @ApplicationScoped @RunWith
我删除了所有不必要的代码,但这是一个相当复杂的单元测试,带有模拟、通过 CDI 进行服务注入以及一些预计会引发异常的测试方法。
import org.jglue.cdiunit.CdiRunner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(CdiRunner.class)
public class FooBarTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void test() {
}
}
所以我的问题是,一方面 Weld 希望所有字段都不是 public,否则它将无法代理 class,另一方面,JUnit 想要 Rule字段是 public 因为它使用反射来访问它们并且不想使用 setAccessible(true)
方法,因为在安全管理器处于活动状态的情况下。如何处理这个悖论?
注意:我还发现了 this answer 的提示评论,指出
You can also annotate a method with @Rule, so this would avoid the problem
但是我找不到任何在方法上带有 @Rule
注释的 junit 测试示例,我打算就此提出一个单独的问题。
我找到了解决问题的方法。为了将来参考,这里有一个有效的片段,希望这对其他人有帮助。
import org.jglue.cdiunit.CdiRunner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(CdiRunner.class)
public class FooBarTest {
private ExpectedException thrown = ExpectedException.none();
@Rule
public ExpectedException getThrown() {
return thrown;
}
@Test
public void test() {
thrown.expect(ArithmeticException.class);
int i = 1 / 0;
}
}