使用CdiRunner时BeanManager找不到豆

时间:2018-07-17 14:51:36

标签: java junit cdi bean-manager

考虑以下示例:

public class MyClass {

    private Assembler assembler;

    public Assembler getAssembler() {
        if (assembler == null) {
            assembler = CdiBeanFactory.getCdiBeanFactory().newInstance(Assembler.class);
        }
        return assembler;
    }

}

具有以下测试类:

@RunWith(CdiRunner.class)
public class MyClassTest {

    @Produces
    @Mock
    private Assembler assembler;

    private MyClass classUnderTest;

    @Before
    public void setUp() {
      classUnderTest = new MyClass();
    }

    @Test
    public void test1() {
        classUnderTest.getAssembler();
    }

    @Test
    public void test2() {
        classUnderTest.getAssembler();
    }

}

使用CdiBeanFactory

public class CdiBeanFactory {

    private static BeanManager beanManager;
    private static CdiBeanFactory cdiBeanFactory ;

    private CdiBeanFactory() {}

    private BeanManager getBeanManager() {
        if (beanManager == null) {
            beanManager = getCdiBeanFactory().lookup(BeanManager.class, "java:comp/BeanManager");
        }
        return beanManager;
    }

    public static CdiBeanFactory getCdiBeanFactory() {
        if (cdiBeanFactory == null) {
            cdiBeanFactory = new CdiBeanFactory();
        }
        return cdiBeanFactory;
    }

    @SuppressWarnings("unchecked")
    public <T> T newInstance(Class<T> clazz) {
        try {
            BeanManager internalBeanManager = getBeanManager();
            Set<Bean<?>> beans = internalBeanManager.getBeans(clazz);
            for (Bean<?> bean : beans) {
                Bean<T> typedBean = (Bean<T>) bean;
                CreationalContext<T> creationalContext = internalBeanManager.createCreationalContext(typedBean);
                T t = (T) internalBeanManager.getReference(typedBean, clazz, creationalContext);

                if (beans.size() == 1)
                    return t;

                if (t.getClass().getName().equals(clazz.getName())) {
                    return t;
                }
            }
        } catch (Exception exception) {
            beanManager = null;
            cdiBeanFactory =  null;
            throw new InjectionException(clazz.getName(), exception);
        }
        throw new InjectionException(clazz.getName());
    }

    public <T> T lookup(Class<T> clazz, String jndiName) {
        Object bean = lookup(jndiName);
        return clazz.cast(bean);
    }

    private Object lookup(String jndiName) {
        try {
            return new InitialContext().lookup(jndiName);
        } catch (NamingException ex) {
            throw new IllegalStateException("BeanLocator.context.lookup(jndiName); ist gescheitert. Grund: ", ex);
        }
    }

    public static void setCdiBeanFactory(CdiBeanFactory cdiBeanFactory) {
        CdiBeanFactory.cdiBeanFactory = cdiBeanFactory;
        beanManager = null;
    }

}

如果我从上面运行测试,则会收到以下错误:

javax.enterprise.inject.InjectionException: mypackage.Assembler

at mypackage.CdiBeanFactory.newInstance(CdiBeanFactory.java:70)
at mypackage.MyClass.getAssembler(MyClass.java:12)
at mypackage.MyClassTest.test2(MyClassTest.java:34)
at mypackage.MyClassTest$Proxy$_$$_WeldClientProxy.test2(MyClassTest$Proxy$_$$_WeldClientProxy.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.jglue.cdiunit.CdiRunner$2.evaluate(CdiRunner.java:179)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

如果我在同一个测试中两次调用getter方法(如

),则不会出现问题
@Test
public void test1() {
    classUnderTest.getBeteiligteVOAssembler();
    classUnderTest.getBeteiligteVOAssembler();
}

似乎CdiRunner正在破坏这里的东西。一种解决方法是在类似{p>的tearDown方法中将BeanFactory设置为null

@After
public void tearDown() throws Exception {
    CdiBeanFactory.setCdiBeanFactory(null);
}

但是我不知道为什么会这样。你们中有人可以帮我吗?

0 个答案:

没有答案