<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3 ## 13.3? 集成測試 ### 13.3.1? 概述 集成測試是在單元測試之上,通常是將一個或多個已進行過單元測試的組件組合起來完成的,即集成測試中一般不會出現Mock對象,都是實實在在的真實實現。 對于單元測試,如前邊在進行數據訪問層單元測試時,通過Mock HibernateTemplate對象然后將其注入到相應的DAO實現,此時單元測試只測試某層的某個功能是否正確,對其他層如何提供服務采用Mock方式提供。 對于集成測試,如要進行數據訪問層集成測試時,需要實實在在的HibernateTemplate對象然后將其注入到相應的DAO實現,此時集成測試將不僅測試該層功能是否正確,還將測試服務提供者提供的服務是否正確執行。 使用Spring的一個好處是能非常簡單的進行集成測試,無需依賴web服務器或應用服務器即可完成測試。Spring通過提供一套TestContext框架來簡化集成測試,使用TestContext測試框架能獲得許多好處,如Spring IoC容器緩存、事務管理、依賴注入、Spring測試支持類等等。 ### 13.3.2 Spring TestContext框架支持 Spring TestContext框架提供了一些通用的集成測試支持,主要提供如下支持: 一、**上下文管理及緩存:** 對于每一個測試用例(測試類)應該只有一個上下文,而不是每個測試方法都創建新的上下文,這樣有助于減少啟動容器的開銷,提供測試效率。可通過如下方式指定要加載的上下文: ``` @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( locations={"classpath:applicationContext-resources-test.xml", "classpath:cn/javass/point/dao/applicationContext-hibernate.xml"}) public class GoodsHibernateDaoIntegrationTest { } ``` * **locations:**指定Spring配置文件位置; * **inheritLocations:**如果設置為false,將屏蔽掉父類中使用該注解指定的配置文件位置,默認為true表示繼承父類中使用該注解指定的配置文件位置。 二、**Test Fixture(測試固件)的依賴注入:** Test Fixture可以指運行測試時需要的任何東西,一般通過@Before定義的初始化Fixture方法準備這些資源,而通過@After定義的銷毀Fixture方法銷毀或還原這些資源。 Test Fixture的依賴注入就是使用Spring IoC容器的注入功能準備和銷毀這些資源。可通過如下方式注入Test Fixture: ``` @Autowired private IGoodsDao goodsDao; @Autowired private ApplicationContext ctx; ``` 即可以通過Spring提供的注解實現Bean的依賴注入來完成Test Fixture的依賴注入。 **三、事務管理:?** 開啟測試類的事務管理支持,即使用Spring 容器的事務管理功能,從而可以獨立于應用服務器完成事務相關功能的測試。為了使測試中的事務管理起作用需要通過如下方式開啟測試類事務的支持: ``` @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( locations={"classpath:applicationContext-resources-test.xml", "classpath:cn/javass/point/dao/applicationContext-hibernate.xml"}) @TransactionConfiguration( transactionManager = "txManager", defaultRollback=true) public class GoodsHibernateDaoIntegrationTest { } ``` Spring提供如下事務相關注解來支持事務管理: * @Transactional:使用@Transactional注解的類或方法將得到事務支持? * **transactionManager:**指定事務管理器; * **defaultRollback:**是否回滾事務,默認為true表示回滾事務。 Spring還通過提供如下注解來簡化事務測試: * **@Transactional:**使用@Transactional注解的類或方法表示需要事務支持; * **@NotTransactional:**只能注解方法,使用@NotTransactional注解的方法表示不需要事務支持,即不運行在事務中,Spring 3開始已不推薦使用; * **@BeforeTransaction和@AfterTransaction:**使用這兩個注解注解的方法定義了在一個事務性測試方法之前或之后執行的行為,且被注解的方法將運行在該事務性方法的事務之外。 * **@Rollback(true)**:默認為true,用于替換@TransactionConfiguration中定義的defaultRollback指定的回滾行為。 **四、常用注解支持:**Spring框架提供如下注解來簡化集成測試: * **@DirtiesContext:**表示每個測試方法執行完畢需關閉當前上下文并重建一個全新的上下文,即不緩存上下文。可應用到類或方法級別,但在JUnit 3.8中只能應用到方法級別。 * **@ExpectedException:**表示被注解的方法預期將拋出一個異常,使用如@ExpectedException(NotCodeException.class)來指定異常,定義方式類似于Junit 4中的@Test(expected = NotCodeException.class),@ExpectedException注解和@Test(expected =……)應該兩者選一。 * @Repeat:**表示被注解的方法應被重復執行多少次,使用如@Repeat(2)方式指定。** * **@Timed:**表示被注解的方法必須在多長時間內運行完畢,超時將拋出異常,使用如@Timed(millis=10)方式指定,單位為毫秒。注意此處指定的時間是如下方法執行時間之和:測試方法執行時間(或者任何測試方法重復執行時間之和)、@Before和@After注解的測試方法之前和之后執行的方法執行時間。而Junit 4中的@Test(timeout=2)指定的超時時間只是測試方法執行時間,不包括任何重復等。 * **除了支持如上注解外,還支持【第十二章?零配置】中依賴注入等注解。** **五、TestContext框架支持類:**提供對測試框架的支持,如Junit、TestNG測試框架,用于集成Spring TestContext和測試框架來簡化測試,TestContext框架提供如下支持類: * **JUnit 3.8支持類:**提供對Spring TestContext框架與Junit3.8測試框架的集成: **AbstractJUnit38SpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。 **AbstractTransactionalJUnit38SpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。 * **JUnit 4.5+支持類:**提供對Spring TestContext框架與Junit4.5+測試框架的集成: **AbstractJUnit4SpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。 **AbstractTransactionalJUnit4SpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。 * **定制 Junit4.5+運行器:**通過定制自己的Junit4.5+運行器從而無需繼承JUnit 4.5+支持類即可完成需要的功能,如Test Fixture的依賴注入、事務管理支持, **@RunWith(SpringJUnit4ClassRunner.class):**使用該注解注解到測試類上表示將集成Spring TestContext和Junit 4.5+測試框架。 **@TestExecutionListeners:**該注解用于指定TestContext框架的監聽器用于與TestContext框架管理器發布的測試執行事件進行交互,TestContext框架提供如下三個默認的監聽器:DependencyInjectionTestExecutionListener、DirtiesContextTestExecutionListener、TransactionalTestExecutionListener分別完成對Test Fixture的依賴注入、@DirtiesContext支持和事務管理支持,即在默認情況下將自動注冊這三個監聽器,另外還可以使用如下方式指定監聽器: ``` @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({}) public class GoodsHibernateDaoIntegrationTest { } ``` 如上配置將通過定制的Junit4.5+運行器運行,但不會完成Test Fixture的依賴注入、事務管理等等,如果只需要Test Fixture的依賴注入,可以使用@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})指定。 * **TestNG支持類:**提供對Spring TestContext框架與TestNG測試框架的集成: **AbstractTestNGSpringContextTests:**我們的測試類繼承該類后將獲取到Test Fixture的依賴注入好處。 **AbstractTransactionalTestNGSpringContextTests:**我們的測試類繼承該類后除了能得到Test Fixture的依賴注入好處,還額外獲取到事務管理支持。 到此Spring TestContext測試框架減少完畢了,接下來讓我們學習一下如何進行集成測試吧。 ### 13.3.3??????? 準備集成測試環境 對于集成測試環境各種配置應該和開發環境或實際生產環境配置相分離,即集成測試時應該使用單獨搭建一套獨立的測試環境,不應使用開發環境或實際生產環境的配置,從而保證測試環境、開發、生產環境相分離。 1、拷貝一份Spring資源配置文件applicationContext-resources.xml,并命名為applicationContext-resources-test.xml表示用于集成測試使用,并修改如下內容: ``` <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:resources-test.properties</value> </list> </property> </bean> ``` **2、拷貝一份替換配置元數據的資源文件(resources/resources.properties),并命名為resources-test.properties表示用于集成測試使用,并修改為以下內容:** ``` db.driver.class=org.hsqldb.jdbcDriver db.url=jdbc:hsqldb:mem:point_shop db.username=sa db.password= #Hibernate屬性 hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.hbm2ddl.auto=create-drop hibernate.show_sql=false hibernate.format_sql=true ``` * **jdbc:hsqldb:mem:point_shop:**我們在集成測試時將使用HSQLDB,并采用內存數據庫模式運行; * **hibernate.hbm2ddl.auto=create-drop**:表示在創建SessionFactory時根據Hibernate映射配置創建相應Model的表結構,并在SessionFactory關閉時刪除這些表結構。 到此我們測試環境修改完畢,在進行集成測試時一定要保證測試環境、開發環境、實際生產環境相分離,即對于不同的環境使用不同的配置文件。 ### 13.3.4? 數據訪問層 數據訪問層集成測試,同單元測試一樣目的不僅測試該層定義的接口實現方法的行為是否正確,而且還要測試是否正確與數據庫交互,是否發送并執行了正確的SQL,SQL執行成功后是否正確的組裝了業務邏輯層需要的數據。 數據訪問層集成測試不再通過Mock對象與數據庫交互的API來完成測試,而是使用實實在在存在的與數據庫交互的對象來完成測試。 接下來讓我們學習一下如何進行數據訪問層集成測試: **1、在test文件夾下創建如下測試類:** ``` package cn.javass.point.dao.hibernate; //省略import @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( locations={"classpath:applicationContext-resources-test.xml", "classpath:cn/javass/point/dao/applicationContext-hibernate.xml"}) @TransactionConfiguration(transactionManager = "txManager", defaultRollback=false) public class GoodsHibernateDaoIntegrationTest { @Autowired private ApplicationContext ctx; @Autowired private IGoodsCodeDao goodsCodeDao; } ``` * **@RunWith(SpringJUnit4ClassRunner.class):**表示使用自己定制的Junit4.5+運行器來運行測試,即完成Spring TestContext框架與Junit集成; * **@ContextConfiguration:**指定要加載的Spring配置文件,此處注意我們的Spring資源配置文件為“applicationContext-resources-test.xml”; * **@TransactionConfiguration:**開啟測試類的事務管理支持配置,并指定事務管理器和默認回滾行為; * **@Autowired:**完成Test Fixture(測試固件)的依賴注入。 **2、測試支持寫完后,接下來測試一下分頁查詢所有已發布的商品是否滿足需求:** ``` @Transactional @Rollback @Test public void testListAllPublishedSuccess() { GoodsModel goods = new GoodsModel(); goods.setDeleted(false); goods.setDescription(""); goods.setName("測試商品"); goods.setPublished(true); goodsDao.save(goods); Assert.assertTrue(goodsDao.listAllPublished(1).size() == 1); Assert.assertTrue(goodsDao.listAllPublished(2).size() == 0); } ``` * **@Transactional:**表示測試方法將允許在事務環境; * **@Rollback:**表示替換@ContextConfiguration指定的默認事務回滾行為,即將在測試方法執行完畢時回滾事務。 數據訪問層的集成測試也是非常簡單,與數據訪問層的單元測試類似,也應該只對復雜的數據訪問層代碼進行測試。 ### 13.3.5? 業務邏輯層 業務邏輯層集成測試,目的同樣是測試該層的業務邏輯是否正確,對于數據訪問層實現通過Spring IoC容器完成裝配,即使用真實的數據訪問層實現來獲取相應的底層數據。 接下來讓我們學習一下如何進行業務邏輯層集成測試: **1、在test文件夾下創建如下測試類:** ``` @ContextConfiguration( locations={"classpath:applicationContext-resources-test.xml", "classpath:cn/javass/point/dao/applicationContext-hibernate.xml", "classpath:cn/javass/point/service/applicationContext-service.xml"}) @TransactionConfiguration(transactionManager = "txManager", defaultRollback=false) public class GoodsCodeServiceImplIntegrationTest extends AbstractJUnit4SpringContextTests { @Autowired private IGoodsCodeService goodsCodeService; @Autowired private IGoodsService goodsService; } ``` * **AbstractJUnit4SpringContextTests:**表示將Spring TestContext框架與Junit4.5+測試框架集成; * **@ContextConfiguration:**指定要加載的Spring配置文件,此處注意我們的Spring資源配置文件為“applicationContext-resources-test.xml”; * **@TransactionConfiguration:**開啟測試類的事務管理支持配置,并指定事務管理器和默認回滾行為; * **@Autowired:**完成Test Fixture(測試固件)的依賴注入。 **2、測試支持寫完后,接下來測試一下購買商品Code碼是否滿足需求:** **2.1、測試購買失敗的場景:** ``` @Transactional @Rollback @ExpectedException(NotCodeException.class) @Test public void testBuyFail() { goodsCodeService.buy("test", 1); } ``` 由于我們數據庫中沒有相應商品的Code碼,因此將拋出NotCodeException異常。 **2.2、測試購買成功的場景:** ``` @Transactional @Rollback @Test public void testBuySuccess() { //1.添加商品 GoodsModel goods = new GoodsModel(); goods.setDeleted(false); goods.setDescription(""); goods.setName("測試商品"); goods.setPublished(true); goodsService.save(goods); //2.添加商品Code碼 GoodsCodeModel goodsCode = new GoodsCodeModel(); goodsCode.setGoods(goods); goodsCode.setCode("test"); goodsCodeService.save(goodsCode); //3.測試購買商品Code碼 GoodsCodeModel resultGoodsCode = goodsCodeService.buy("test", 1); Assert.assertEquals(goodsCode.getId(), resultGoodsCode.getId()); } ``` 由于我們添加了指定商品的Code碼因此購買將成功,如果失敗說明業務寫錯了,應該重寫。 業務邏輯層的集成測試也是非常簡單,與業務邏輯層的單元測試類似,也應該只對復雜的業務邏輯層代碼進行測試。 ### 13.3.5? 表現層 對于表現層集成測試,同樣類似于單元測試,但對于業務邏輯層都將使用真實的實現,而不再是通過Mock對象來測試,這也是集成測試和單元測試的區別。 接下來讓我們學習一下如何進行表現層Action集成測試: **1、準備Struts提供的junit插件,?到struts-2.2.1.1.zip中拷貝如下jar包到類路徑:** ``` lib\struts2-junit-plugin-2.2.1.1.jar ``` **2、測試支持類:**Struts2提供StrutsSpringTestCase測試支持類,我們所有的Action測試類都需要繼承該類; **3、準備Spring配置文件:**由于我們的測試類繼承StrutsSpringTestCase且將通過覆蓋該類的getContextLocations方法來指定Spring配置文件,但由于getContextLocations方法只能返回一個配置文件,因此我們需要新建一個用于導入其他Spring配置文件的配置文件applicationContext-test.xml,具體內容如下: ``` <import resource="classpath:applicationContext-resources-test.xml"/> <import resource="classpath:cn/javass/point/dao/applicationContext-hibernate.xml"/> <import resource="classpath:cn/javass/point/service/applicationContext-service.xml"/> <import resource="classpath:cn/javass/point/web/pointShop-admin-servlet.xml"/> <import resource="classpath:cn/javass/point/web/pointShop-front-servlet.xml"/> ``` **3、在test文件夾下創建如下測試類:** ``` package cn.javass.point.web.front; //省略import @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({}) public class GoodsActionIntegrationTest extends StrutsSpringTestCase { @Override protected String getContextLocations() { return "classpath:applicationContext-test.xml"; } @Before public void setUp() throws Exception { //1 指定Struts2配置文件 //該方式等價于通過web.xml中的<init-param>方式指定參數 Map<String, String> dispatcherInitParams = new HashMap<String, String>(); ReflectionTestUtils.setField(this, "dispatcherInitParams", dispatcherInitParams); //1.1 指定Struts配置文件位置 dispatcherInitParams.put("config", "struts-default.xml,struts-plugin.xml,struts.xml"); super.setUp(); } @After public void tearDown() throws Exception { super.tearDown(); } } ``` * **@RunWith(SpringJUnit4ClassRunner.class):**表示使用自己定制的Junit4.5+運行器來運行測試,即完成Spring TestContext框架與Junit集成; * **@TestExecutionListeners({}):**沒有指定任何監聽器,即不會自動完成對Test Fixture的依賴注入、@DirtiesContext支持和事務管理支持; * **StrutsSpringTestCase:**集成測試Struts2+Spring時所有集成測試類必須繼承該類; * **setUp方法:**在每個測試方法之前都執行的初始化方法,其中dispatcherInitParams用于指定等價于在web.xml中的&lt;init-param&gt;方式指定的參數;必須調用super.setUp()用于初始化Struts2和Spring環境。 * **tearDown():**在每個測試方法之前都執行的銷毀方法,必須調用super.tearDown()來銷毀Spring容器等。 **4、測試支持寫完后,接下來測試一下前臺購買商品Code碼是否滿足需求:** **4.1、測試購買失敗的場景:** ``` @Test public void testBuyFail() throws UnsupportedEncodingException, ServletException { //2 前臺購買商品失敗 //2.1 首先重置hhtp相關對象,并準備準備請求參數 initServletMockObjects(); request.setParameter("goodsId", String.valueOf(Integer.MIN_VALUE)); //2.2 調用前臺GoodsAction的buy方法完成購買相應商品的Code碼 executeAction("/goods/buy.action"); GoodsAction frontGoodsAction = (GoodsAction) ActionContext.getContext().getActionInvocation().getAction(); //2.3 驗證前臺GoodsAction的buy方法有錯誤 Assert.assertTrue(frontGoodsAction.getActionErrors().size() > 0); } ``` * **initServletMockObjects()**:用于重置所有http相關對象,如request等; * **request.setParameter("goodsId", String.valueOf(Integer.MIN_VALUE))**:用于準備請求參數; * **executeAction("/goods/buy.action"):**通過模擬http請求來調用前臺GoodsAction的buy方法完成商品購買 * **Assert.assertTrue(frontGoodsAction.getActionErrors().size() &gt; 0)**:表示執行Action時有錯誤,即Action動作錯誤。如果條件不成立,說明我們Action功能是錯誤的,需要修改。 **4.2、測試購買成功的場景:** ``` @Test public void testBuySuccess() throws UnsupportedEncodingException, ServletException { //3 后臺新增商品 //3.1 準備請求參數 request.setParameter("goods.name", "測試商品"); request.setParameter("goods.description", "測試商品描述"); request.setParameter("goods.originalPoint", "1"); request.setParameter("goods.nowPoint", "2"); request.setParameter("goods.published", "true"); //3.2 調用后臺GoodsAction的add方法完成新增 executeAction("/admin/goods/add.action"); //2.3 獲取GoodsAction的goods屬性 GoodsModel goods = (GoodsModel) findValueAfterExecute("goods"); //4 后臺新增商品Code碼 //4.1 首先重置hhtp相關對象,并準備準備請求參數 initServletMockObjects(); request.setParameter("goodsId", String.valueOf(goods.getId())); request.setParameter("codes", "a\rb"); //4.2 調用后臺GoodsCodeAction的add方法完成新增商品Code碼 executeAction("/admin/goodsCode/add.action"); //5 前臺購買商品成功 //5.1 首先重置hhtp相關對象,并準備準備請求參數 initServletMockObjects(); request.setParameter("goodsId", String.valueOf(goods.getId())); //5.2 調用前臺GoodsAction的buy方法完成購買相應商品的Code碼 executeAction("/goods/buy.action"); GoodsAction frontGoodsAction = (GoodsAction) ActionContext.getContext().getActionInvocation().getAction(); //5.3 驗證前臺GoodsAction的buy方法沒有錯誤 Assert.assertTrue(frontGoodsAction.getActionErrors().size() == 0); } ``` * **executeAction("/admin/goods/add.action"):**調用后臺GoodsAction的add方法,用于新增商品; * **executeAction("/admin/goodsCode/add.action"):**調用后臺GoodCodeAction的add方法用于新增商品Code碼; * **executeAction("/goods/buy.action"):**調用前臺GoodsAction的buy方法,用于購買相應商品,其中Assert.assertTrue(frontGoodsAction.getActionErrors().size() == 0)表示購買成功,即Action動作正確。 表現層Action集成測試介紹就到此為止,如何深入StrutsSpringTestCase來完成集成測試已超出本書范圍,如果讀者對這部分感興趣可以到Struts2官網學習最新的測試技巧。 原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/0/2557.html](http://sishuok.com/forum/blogPost/list/0/2557.html#7333)】
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看