7

以下代码片段足以重现我的问题:

  • 要么我设置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修饰符就位并@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 希望所有字段都不公开,因为否则它将无法代理类,另一方面,JUnit 希望 Rule 字段公开,因为它使用反射来访问它们和setAccessible(true)由于安全管理器处于活动状态,因此不想使用该方法。如何处理这个悖论?

注意:我还发现了对此答案的提示评论,指出

你也可以用@Rule注解一个方法,这样可以避免这个问题

但是我找不到任何带有@Rule方法注释的 junit 测试示例,我打算就此提出一个单独的问题。

4

1 回答 1

16

我发现了如何解决这个问题。为了将来参考,这里是一个有效的片段,希望这对其他人有帮助。

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;
    }
}
于 2016-10-21T12:24:29.557 回答