我们正在将JavaEE应用程序从Weblogic 10.3.6迁移到Weblogic 12.2.1.2。作为此迁移的一部分,我们正在更改我们的JSF管理bean以使用CDI注释而不是标准的JSF注释。 @ManagedBean
到@Named
和javax.faces.bean.ViewScoped
到javax.faces.view.ViewScoped
。事实证明这只是一个小问题。但是我试图让我们的测试运行有一个大问题。测试失败,出现以下错误:
WebBeans context with scope type annotation @ViewScoped does not exist within current thread
我尝试了多个不同的容器(嵌入式和远程)但仍然遇到同样的错误。任何帮助将不胜感激。
我正在使用具有以下pom.xml依赖关系的Arquillian:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.12.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>arquillian-openejb-embedded</artifactId>
<version>7.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>javax.faces-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.0.13</version>
</dependency>
<dependency>
<groupId>org.primefaces.themes</groupId>
<artifactId>all-themes</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
BackingBean:
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
@Named
@ViewScoped
public class AnotherBean implements Serializable {
public String doTest()
{
System.out.println("test");
return "test";
}
}
testBean这个
@RunWith(Arquillian.class)
public class TestAgain {
@Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClass(AnotherBean.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Inject
AnotherBean anotherBean;
@Test
public void doTest()
{
Assert.assertEquals(anotherBean.doTest(), "test");
anotherBean.doTest();
}
}
更新
如果我将@Deployment更改为:
@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "test.jar")
.addClass(AnotherBean.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
我得到:
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [AnotherBean] is not found with the qualifiers
Qualifiers: [@javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name : anotherBean, Bean Owner : [null]
答案 0 :(得分:0)
我们在测试@ViewScoped bean时遇到类似的困难。我们通过在测试中自己创建了注入来解决这个问题。
Bean实例本身是在测试中创建的,然后通过使用反射将所有依赖项插入到该实例中。这适用于bean,entitymanger等
@RunWith(Arquillian.class)
public class ViewControllerTest {
@Inject private OtherBean otherBean;
private ViewController viewController;
@Deployment
public static WebArchive createDeployment() {
return WebArchiveFactory.getDefaultWebarchArchive();
}
@Before
public void setup() throws Exception {
viewController = new ViewController();
TestHelper.setFacesContext(); // provide FacesContextMock
TestHelper.inject(viewController, "otherBean", otherBean);
}
}
TestHelper看起来像这样
public class TestHelper {
public static void inject(Object bean,
String fieldName,
Object fieldValue) throws Exception {
if (null == bean) {
throw new IllegalArgumentException("Bean must not be null");
}
Field field;
try {
field = bean.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
log.log(Level.SEVERE, "Could not find field for injection: " + fieldName);
throw e;
}
field.setAccessible(true);
field.set(bean, fieldValue);
}
}
答案 1 :(得分:0)
最后,我不得不用一个老式的黑客解决这个问题。我找到了原始org.apache.webbeans.container.BeanManagerImpl
来自的WebBeans context with scope type annotation @ViewScoped does not exist within current thread
的来源。我在测试源中创建了这个类,然后我做了一些更改来解决问题。
最终,对于我的测试,我不关心范围。我正在测试方法运行并返回正确的逻辑/数据。因此,在类中,它会检查bean所在的范围类型并抛出异常。我只是检查它是否在Viewscoped
,如果是,则将其更改为Dependent
。这样就可以让我的测试工作了。
不是最好的解决方案,但它有效。