UserCredentials
。 在集成測試中,通常沒有HttpRequest或HttpSession可以使用(至少在不進行包含用戶界面的測試時)。 因此,您需要一些基礎架構來進行集成測試。 使用這兩種技術,使此基礎結構正常運行有點令人困惑。 獲取您自己的照片。 如果您不熟悉CDI和Spring中的范圍和上下文,請查看基礎知識并獲得有關不同范圍的概述。
在Spring中集成測試作用域的bean
在Spring 3.1中,沒有針對作用域會話或請求Bean的集成測試支持(請參閱此處 )。 它計劃在Spring版本3.2中使用。 但是, 此鏈接說明了適用于我的解決方案。
首先,您需要為測試開發一個SessionScope。 目的是模擬HttpRequest和HttpSession。
package com.mycompany.springapp.scope;import org.springframework.beans.factory.InitializingBean;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.SessionScope;public class SetupSession extends SessionScope implements InitializingBean {public void afterPropertiesSet() throws Exception {MockHttpServletRequest request = new MockHttpServletRequest();MockHttpSession session = new MockHttpSession();request.setSession(session);RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));}}
要在您的test-beans.xml
中將該類注冊為會話范圍管理對象,請執行以下操作:
注意,我在context:component-scan
標記之后注冊了作用域 。
最后,我編寫了我的測試課:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;@ContextConfiguration("/test-beans.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class MyScopeBeanTest {@Autowiredprivate MyScopeBean myScopeBean;@Testpublic void testBeanScopes() {Assert.isTrue(myScopeBean.getMyCustomScopedService().getName().equals("Test"));Assert.isTrue(myScopeBean.getMySessionScopedService().getName().equals("Test"));}}
注意,我已經在作用域bean上調用了方法getName()
。 這對于確保范圍確定有效。 客戶端代理可能會在注入點被注入,但是如果您對代理進行調用,則它不會分別引用作用域對象和協作對象。
使用CDI集成測試作用域的bean
我用于集成測試CDI的工具是Arquillian 。 還有其他選擇。 如果僅使用CDI類進行測試,則可以“本地”使用Weld。 但是,如果您也有EJB,那還不夠。 Arquillian帶有相當數量的傳遞依賴項。 讓我們來看看如何使事情發展。
注意:沒有Maven,您會迷失在這里的沙漠中,因此,我鼓勵您使用它! 我已經為Helios嘗試了m2eclipse,但對我來說卻不起作用,我使用Maven 3返回了舊的命令行。
pom.xml
文件的更改 這些示例假定您有一個Java EE項目正在運行,您還可以在此處查看如何設置新的Java EE 6項目。 要集成Arquillian,請對pom.xml
文件進行以下更改:
在屬性部分:
1.0.0.Alpha5
添加此存儲庫:
repository.jboss.orghttp://repository.jboss.org/nexus/content/groups/publicdefaulttrueneverwarnfalsealwayswarn
這是官方的JBoss Maven存儲庫,所有Arquillian發行版都在其中。
將以下依賴項添加到pom.xml
:
junit junit 4.8.1 test org.jboss.arquillianarquillian-junit${arquillian.version}testorg.jboss.arquillian.containerarquillian-glassfish-remote-3.1${arquillian.version}testjavax.enterprisecdi-api1.0-SP4test
第一個依賴項是您的JUnit框架來編寫集成測試。 第二個依賴項將Arquillian與JUnit集成在一起。 第三個依賴項集成了您的部署容器。 對我來說,這是我的Glassfish安裝。 最后一個依賴項是CDI API,該CDI API需要可用于CDI測試。
請注意,在第17行中,我將我的Glassfish 3.1安裝用作部署容器,而Arquillian使用遠程調用來執行測試。 您需要在此處配置自己的部署環境。 有關正確的artifactId
值,請參見JBoss Maven Repo 。 使用Arquillian,您的目標環境也可以是嵌入式容器,例如JBoss Embedded AS,GlassFish Embedded或Weld SE。 在那種情況下,您不需要單獨的容器安裝和遠程調用,它們都在本地運行(“內存中”)。
在為目標環境添加依賴項之后,您可以執行mvn eclipse:eclipse。
最后,我編寫了我的第一個Arquillian集成測試類:
import javax.inject.Inject;import junit.framework.Assert;import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;import com.mycompany.jeeapp.scope.MyApplicationService;
import com.mycompany.jeeapp.scope.MyConversationService;
import com.mycompany.jeeapp.scope.MyDefaultService;
import com.mycompany.jeeapp.scope.MyRequestService;
import com.mycompany.jeeapp.scope.MyScopeBean;
import com.mycompany.jeeapp.scope.MySessionService;
import com.mycompany.jeeapp.scope.MySingletonService;
import com.mycompany.jeeapp.scope.extension.MyCustomScopeService;@RunWith(Arquillian.class)
public class MyArquillianJUnitTest {@Injectprivate MyScopeBean myScopeBean;@Deploymentpublic static JavaArchive createTestArchive() {return ShrinkWrap.create(JavaArchive.class, "test.jar").addClasses(MyScopeBean.class,MyApplicationService.class,MyConversationService.class, MyDefaultService.class,MyRequestService.class, MySessionService.class,MySingletonService.class, MyCustomScopeService.class).addAsManifestResource(EmptyAsset.INSTANCE,ArchivePaths.create("beans.xml"));}@Testpublic void testScopedBeans() {Assert.assertTrue(myScopeBean.getApplicationService().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getApplicationServiceWithNew().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getCustomScopeService().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getDefaultService().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getRequestService().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getSessionService().getSomeName().equals("myName"));Assert.assertTrue(myScopeBean.getSingletonService().getSomeName().equals("myName"));}}
結論
Spring目前不為作用域bean提供集成測試支持。 令人驚訝的是,Spring一直非常重視所有測試主題。 我在博客中描述了一種解決方法。 完成這項工作并不難。 計劃對3.2 M1版本提供完全集成測試支持。
Arquillian啟用了CDI范圍的bean測試。 我在設置過程中遇到了一些問題(請參閱下面的最后一段),如果您使用新技術,我認為這很常見。 您必須將所有測試中的bean傳遞到歸檔文件(請參閱@Deployment
方法)這一事實是我需要在大型項目中嘗試的:這真的是一個好主意嗎? 有時,大型應用程序與來自不同程序包的數十個bean連接在一起。 很難預測在集成測試中使用了哪些bean。
問題與解決方案
一些Arquillian設置帶有很多依賴項,以致您不能使用標準的Eclipse啟動配置。 生成的命令行參數超出了Windows命令行指令的長度限制。 因此,我已使用Ant腳本開始測試。 該腳本僅用于說明。 您必須構建自己的Ant腳本。 您可以按照以下方式獲取類路徑信息:在Eclipse中,轉到“文件>導出>常規> Ant構建文件”以生成您的類路徑信息。 獲取此類路徑信息,并將其放入Ant JUnit測試啟動腳本中。 我已經在這里記錄了完整的Ant腳本 。
當我啟動此Ant腳本時,一切對我來說都很好。 如果您有任何問題要告訴我,可以查看測試結果文件和server.log
進行分析。
WELD-001303范圍類型javax.enterprise.context.ConversationScoped沒有活動上下文
-> ConversationScope通過EE規范綁定到JSF。 因此,在Arquillian背負的正常HTTP請求期間,它們將不會處于活動狀態。
POST http:// localhost:4848 / management / domain / applications / application返回的響應狀態為403
-> 404/403錯誤可能是部署問題,請檢查server.log的根本原因(我是沒有將所有必需的類添加到test.jar
)
執行命令行時發生異常。
無法運行程序“ D:\ dev_home \ java-6-26 \ bin \ javaw.exe”(在目錄“ D:\ dev_home \ repositories \ git \ jee-app-weld \ jee-app-weld”中):CreateProcess錯誤= 87,Falscher參數
->類路徑超出Windows命令行操作允許的長度。 您需要使用Ant腳本或Maven來運行測試。
ValidationException:DeploymentScenario包含未在注冊表中緩存任何已定義容器的目標
->看到這里 。
WELD-000072聲明鈍化作用域的托管bean必須具有鈍化能力。 Bean:具有限定符[@Any @Default]的托管Bean [com.mycompany.jeeapp.scope.example.UserCredentials類]
->您需要在會話和會話范圍的bean上實現Serializable。
DeploymentScenario包含不在注冊表中緩存任何定義的Container的目標。 _默認_
->看到這里 。
java.net.ConnectException:連接被拒絕:connect
->您的遠程Java EE服務器安裝未運行,請啟動它!
參考:來自我們JCG合作伙伴 Niklas的“在CDI 1.0和Spring 3.1中對作用域Bean進行集成測試”。
翻譯自: https://www.javacodegeeks.com/2012/01/integration-testing-scoped-beans-in-cdi.html