考虑以下示例:
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);
}
但是我不知道为什么会这样。你们中有人可以帮我吗?