摘要:本章目的基于平臺(tái)整合分別完成客戶端服務(wù)端的單元測(cè)試。在測(cè)試控制器內(nèi)添加了三個(gè)測(cè)試方法,我們接下來(lái)開(kāi)始編寫單元測(cè)試代碼。總結(jié)本章主要介紹了基于平臺(tái)的兩種單元測(cè)試方式,一種是在服務(wù)端采用注入方式將需要測(cè)試的或者注入到測(cè)試類中,然后調(diào)用方法即可。
單元測(cè)試對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)是非常熟悉的,我們每天的工作也都是圍繞著開(kāi)發(fā)與測(cè)試進(jìn)行的,在最早的時(shí)候測(cè)試都是采用工具Debug模式進(jìn)行調(diào)試程序,后來(lái)Junit的誕生也讓程序測(cè)試發(fā)生了很大的變化。我們今天來(lái)講解下基于SpringBoot結(jié)合Junit怎么來(lái)完成單元測(cè)試。
本章目的基于SpringBoot平臺(tái)整合Junit分別完成客戶端、服務(wù)端的單元測(cè)試。
構(gòu)建項(xiàng)目我們首先使用idea工具創(chuàng)建一個(gè)SpringBoot項(xiàng)目,并且添加相關(guān)Web、MySQL、JPA依賴,具體pom.xml配置依賴內(nèi)容如下所示:
.../省略其他配置配置數(shù)據(jù)庫(kù).../省略其他配置 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.alibaba druid 1.0.31 org.projectlombok lombok mysql mysql-connector-java org.springframework.boot spring-boot-starter-test test
我們本章的內(nèi)容需要訪問(wèn)數(shù)據(jù)庫(kù),我們先在src/main/resources下添加application.yml配置文件,對(duì)應(yīng)添加數(shù)據(jù)庫(kù)配置信息如下所示:
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8 username: root password: 123456 #最大活躍數(shù) maxActive: 20 #初始化數(shù)量 initialSize: 1 #最大連接等待超時(shí)時(shí)間 maxWait: 60000 #打開(kāi)PSCache,并且指定每個(gè)連接PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 #通過(guò)connectionProperties屬性來(lái)打開(kāi)mergeSql功能;慢SQL記錄 #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 1 from dual testWhileIdle: true testOnBorrow: false testOnReturn: false #配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql將無(wú)法統(tǒng)計(jì),"wall"用于防火墻 filters: stat, wall, log4j jpa: properties: hibernate: show_sql: true format_sql: true
以上配置都是比較常用到,這里不做多解釋了,如果不明白可以去本文底部SpringBoot學(xué)習(xí)目錄文章內(nèi)找尋對(duì)應(yīng)的章節(jié)。
構(gòu)建實(shí)體對(duì)應(yīng)數(shù)據(jù)庫(kù)內(nèi)的數(shù)據(jù)表來(lái)創(chuàng)建一個(gè)商品基本信息實(shí)體,實(shí)體內(nèi)容如下所示:
package com.yuqiyu.chapter35.bean; import lombok.Data; import javax.persistence.*; import java.io.Serializable; /** * 商品基本信息實(shí)體 * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/9/13 * Time:22:20 * 碼云:http://git.oschina.net/jnyqy * ======================== */ @Data @Entity @Table(name = "good_infos") public class GoodInfoEntity implements Serializable { //商品編號(hào) @Id @Column(name = "tg_id") @GeneratedValue private Integer tgId; //商品類型編號(hào) @Column(name = "tg_type_id") private Integer typeId; //商品標(biāo)題 @Column(name = "tg_title") private String title; //商品價(jià)格 @Column(name = "tg_price") private double price; //商品排序 @Column(name = "tg_order") private int order; }構(gòu)建JPA
基于商品基本信息實(shí)體類創(chuàng)建一個(gè)JPA接口,該接口繼承JpaRepository接口完成框架通過(guò)反向代理模式進(jìn)行生成實(shí)現(xiàn)類,自定義JPA接口內(nèi)容如下所示:
package com.yuqiyu.chapter35.jpa; import com.yuqiyu.chapter35.bean.GoodInfoEntity; import org.springframework.data.jpa.repository.JpaRepository; /** * 商品jpa * ======================== * Created with IntelliJ IDEA. * User:恒宇少年 * Date:2017/9/13 * Time:22:23 * 碼云:http://git.oschina.net/jnyqy * ======================== */ public interface GoodInfoJPA extends JpaRepository構(gòu)建測(cè)試控制器{ }
下面我們開(kāi)始為單元測(cè)試來(lái)做準(zhǔn)備工作,先來(lái)創(chuàng)建一個(gè)SpringMVC控制器來(lái)處理請(qǐng)求,代碼如下所示:
package com.yuqiyu.chapter35.controller; import com.yuqiyu.chapter35.bean.GoodInfoEntity; import com.yuqiyu.chapter35.jpa.GoodInfoJPA; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * =============================== * Created with Eclipse. * User:于起宇 * Date:2017/9/13 * Time:18:37 * 簡(jiǎn)書:http://www.jianshu.com/u/092df3f77bca * ================================ */ @RestController public class TestController { //商品基本信息數(shù)據(jù)接口 @Autowired private GoodInfoJPA goodInfoJPA; /** * 查詢首頁(yè)內(nèi)容 * @return */ @RequestMapping(value = "/index") public String index(String name) { return "this is index page" + name; } /** * 查詢?nèi)可唐? * @return */ @RequestMapping(value = "/all") public ListselectAll() { return goodInfoJPA.findAll(); } /** * 查詢商品詳情 * @param goodId * @return */ @RequestMapping(value = "/detail",method = RequestMethod.GET) public GoodInfoEntity selectOne(Integer goodId) { return goodInfoJPA.findOne(goodId); } }
我們?cè)跍y(cè)試控制內(nèi)注入了GoodInfoJPA,獲得了操作商品基本信息的數(shù)據(jù)接口代理實(shí)例,我們可以通過(guò)該代理實(shí)例去做一些數(shù)據(jù)庫(kù)操作,如上代碼selectAll、detail方法所示。
在測(cè)試控制器內(nèi)添加了三個(gè)測(cè)試MVC方法,我們接下來(lái)開(kāi)始編寫單元測(cè)試代碼。
在我們使用idea開(kāi)發(fā)工具構(gòu)建完成SpringBoot項(xiàng)目后,會(huì)自動(dòng)為我們添加spring-boot-starter-test依賴到pom.xml配置文件內(nèi),當(dāng)然也為我們自動(dòng)創(chuàng)建了一個(gè)測(cè)試類,該類內(nèi)一開(kāi)始是沒(méi)有過(guò)多的代碼的。
下面我們開(kāi)始基于該測(cè)試類進(jìn)行添加邏輯,代碼如下所示:
....//省略依賴導(dǎo)包 /** * 單元測(cè)試 */ @RunWith(SpringRunner.class) @SpringBootTest public class Chapter35ApplicationTests { /** * 模擬mvc測(cè)試對(duì)象 */ private MockMvc mockMvc; /** * web項(xiàng)目上下文 */ @Autowired private WebApplicationContext webApplicationContext; /** * 商品業(yè)務(wù)數(shù)據(jù)接口 */ @Autowired private GoodInfoJPA goodInfoJPA; /** * 所有測(cè)試方法執(zhí)行之前執(zhí)行該方法 */ @Before public void before() { //獲取mockmvc對(duì)象實(shí)例 mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } }
在上面測(cè)試代碼中我們從上面開(kāi)始講解下,其中@RunWith這里就不多做解釋了,我們最比較常用到的就是這個(gè)注解。
@SpringBootTest這個(gè)注解這里要強(qiáng)調(diào)下,這是SpringBoot項(xiàng)目測(cè)試的核心注解,標(biāo)識(shí)該測(cè)試類以SpringBoot方式運(yùn)行,該注解的源碼如下所示:
...//省略導(dǎo)包 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @BootstrapWith(SpringBootTestContextBootstrapper.class) public @interface SpringBootTest { @AliasFor("properties") String[] value() default {}; @AliasFor("value") String[] properties() default {}; Class>[] classes() default {}; SpringBootTest.WebEnvironment webEnvironment() default SpringBootTest.WebEnvironment.MOCK; public static enum WebEnvironment { MOCK(false), RANDOM_PORT(true), DEFINED_PORT(true), NONE(false); private final boolean embedded; private WebEnvironment(boolean embedded) { this.embedded = embedded; } public boolean isEmbedded() { return this.embedded; } } }
我們可以看到在@SpringBootTest注解源碼中最為重要的就是@BootstrapWith,該注解才是配置了測(cè)試類的啟動(dòng)方式,以及啟動(dòng)時(shí)使用實(shí)現(xiàn)類的類型。
測(cè)試index請(qǐng)求MockMvc這個(gè)類是一個(gè)被final修飾的類型,該類無(wú)法被繼承使用。這個(gè)類是Spring為我們提供模擬SpringMVC請(qǐng)求的實(shí)例類,該類則是由MockMvcBuilders通過(guò)WebApplicationContext實(shí)例進(jìn)行創(chuàng)建的,初始化MockMvc實(shí)例我們可以看下before方法邏輯。到現(xiàn)在為止我們才是萬(wàn)事俱備就差編寫單元測(cè)試邏輯了,我們首先來(lái)編寫訪問(wèn)/index請(qǐng)求路徑的測(cè)試,具體測(cè)試代碼如下所示:
/** * 測(cè)試訪問(wèn)/index地址 * @throws Exception */ @Test public void testIndex() throws Exception { MvcResult mvcResult = mockMvc .perform(// 1 MockMvcRequestBuilders.get("/index") // 2 .param("name","admin") // 3 ) .andReturn();// 4 int status = mvcResult.getResponse().getStatus(); // 5 String responseString = mvcResult.getResponse().getContentAsString(); // 6 Assert.assertEquals("請(qǐng)求錯(cuò)誤", 200, status); // 7 Assert.assertEquals("返回結(jié)果不一致", "this is index pageadmin", responseString); // 8 }MockMvc解析
我在上面代碼中進(jìn)行了標(biāo)記,我們按照標(biāo)記進(jìn)行講解,這樣會(huì)更明白一些:
1 perform方法其實(shí)只是為了構(gòu)建一個(gè)請(qǐng)求,并且返回ResultActions實(shí)例,該實(shí)例則是可以獲取到請(qǐng)求的返回內(nèi)容。
2 MockMvcRequestBuilders該抽象類則是可以構(gòu)建多種請(qǐng)求方式,如:Post、Get、Put、Delete等常用的請(qǐng)求方式,其中參數(shù)則是我們需要請(qǐng)求的本項(xiàng)目的相對(duì)路徑,/則是項(xiàng)目請(qǐng)求的根路徑。
3 param方法用于在發(fā)送請(qǐng)求時(shí)攜帶參數(shù),當(dāng)然除了該方法還有很多其他的方法,大家可以根據(jù)實(shí)際請(qǐng)求情況選擇調(diào)用。
4 andReturn方法則是在發(fā)送請(qǐng)求后需要獲取放回時(shí)調(diào)用,該方法返回MvcResult 對(duì)象,該對(duì)象可以獲取到返回的視圖名稱、返回的Response狀態(tài)、獲取攔截請(qǐng)求的攔截器集合等。
5 我們?cè)谶@里就是使用到了第4步內(nèi)的MvcResult對(duì)象實(shí)例獲取的MockHttpServletResponse對(duì)象從而才得到的Status狀態(tài)碼。
6 同樣也是使用MvcResult實(shí)例獲取的MockHttpServletResponse對(duì)象從而得到的請(qǐng)求返回的字符串內(nèi)容。【可以查看rest返回的json數(shù)據(jù)】
7 使用Junit內(nèi)部驗(yàn)證類Assert判斷返回的狀態(tài)碼是否正常為200
8 判斷返回的字符串是否與我們預(yù)計(jì)的一樣。
直接上代碼吧,跟上面的代碼幾乎一致,如下所示:
/** * 測(cè)試查詢?cè)斍? * @throws Exception */ @Test public void testDetail() throws Exception { MvcResult mvcResult = mockMvc .perform( MockMvcRequestBuilders.get("/detail") .param("goodId","2") ) .andReturn(); // 5 //輸出經(jīng)歷的攔截器 HandlerInterceptor[] interceptors = mvcResult.getInterceptors(); System.out.println(interceptors[0].getClass().getName()); int status = mvcResult.getResponse().getStatus(); // 6 String responseString = mvcResult.getResponse().getContentAsString(); // 7 System.out.println("返回內(nèi)容:"+responseString); Assert.assertEquals("return status not equals 200", 200, status); // 8 }
上面唯一一個(gè)部分需要解釋下,在上面測(cè)試方法內(nèi)輸出了請(qǐng)求經(jīng)歷的攔截器,如果我們配置了多個(gè)攔截器這里會(huì)根據(jù)先后順序?qū)懭氲綌r截器數(shù)組內(nèi),其他的MockMvc測(cè)試方法以及參數(shù)跟上面測(cè)試方法一致。
測(cè)試添加在測(cè)試類聲明定義全局字段時(shí),我們注入了GoodInfoJPA實(shí)例,當(dāng)然單元測(cè)試也不僅僅是客戶端也就是使用MockMvc方式進(jìn)行的,我們也可以直接調(diào)用JPA、Service進(jìn)行直接測(cè)試。下面我們來(lái)測(cè)試下商品基本信息的添加,代碼如下所示:
/** * 測(cè)試添加商品基本信息 */ @Test public void testInsert() { /** * 商品基本信息實(shí)體 */ GoodInfoEntity goodInfoEntity = new GoodInfoEntity(); goodInfoEntity.setTitle("西紅柿"); goodInfoEntity.setOrder(2); goodInfoEntity.setPrice(5.82); goodInfoEntity.setTypeId(1); goodInfoJPA.save(goodInfoEntity); /** * 測(cè)試是否添加成功 * 驗(yàn)證主鍵是否存在 */ Assert.assertNotNull(goodInfoEntity.getTgId()); }
在上面代碼中并沒(méi)有什么特殊的部分,是我們?cè)谑褂?b>Data JPA時(shí)用到的save方法用于執(zhí)行添加,在添加完成后驗(yàn)證主鍵的值是否存在,NotNull時(shí)證明添加成功。
測(cè)試刪除與添加差別不大,代碼如下所示:
/** * 測(cè)試刪除商品基本信息 */ @Test public void testDelete() { //根據(jù)主鍵刪除 goodInfoJPA.delete(3); //驗(yàn)證數(shù)據(jù)庫(kù)是否已經(jīng)刪除 Assert.assertNull(goodInfoJPA.findOne(3)); }
在上面代碼中,我們根據(jù)主鍵的值進(jìn)行刪除商品的基本信息,執(zhí)行刪除完成后調(diào)用selectOne方法查看數(shù)據(jù)庫(kù)內(nèi)是否已經(jīng)不存在該條數(shù)據(jù)了。
總結(jié)本章主要介紹了基于SpringBoot平臺(tái)的兩種單元測(cè)試方式,一種是在服務(wù)端采用Spring注入方式將需要測(cè)試的JPA或者Service注入到測(cè)試類中,然后調(diào)用方法即可。另外一種則是在客戶端采用MockMvc方式測(cè)試Web請(qǐng)求,根據(jù)傳遞的不用參數(shù)以及請(qǐng)求返回對(duì)象反饋信息進(jìn)行驗(yàn)證測(cè)試。
本章代碼已經(jīng)上傳到碼云:
網(wǎng)頁(yè)地址:http://git.oschina.net/jnyqy/lessons
Git地址:https://git.oschina.net/jnyqy/lessons.git
SpringBoot相關(guān)系列文章請(qǐng)?jiān)L問(wèn):目錄:SpringBoot學(xué)習(xí)目錄
QueryDSL相關(guān)系列文章請(qǐng)?jiān)L問(wèn):QueryDSL通用查詢框架學(xué)習(xí)目錄
SpringDataJPA相關(guān)系列文章請(qǐng)?jiān)L問(wèn):目錄:SpringDataJPA學(xué)習(xí)目錄
感謝閱讀!
歡迎加入QQ技術(shù)交流群,共同進(jìn)步。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/67635.html
摘要:本章目標(biāo)繼承采用形式實(shí)現(xiàn)個(gè)性化配置定制。本章代碼已經(jīng)上傳到碼云網(wǎng)頁(yè)地址地址相關(guān)系列文章請(qǐng)?jiān)L問(wèn)目錄學(xué)習(xí)目錄相關(guān)系列文章請(qǐng)?jiān)L問(wèn)通用查詢框架學(xué)習(xí)目錄相關(guān)系列文章請(qǐng)?jiān)L問(wèn)目錄學(xué)習(xí)目錄感謝閱讀歡迎加入技術(shù)交流群,共同進(jìn)步。 WebMvcConfigurerAdapter配置類其實(shí)是Spring內(nèi)部的一種配置方式,采用JavaBean的形式來(lái)代替?zhèn)鹘y(tǒng)的xml配置文件形式進(jìn)行針對(duì)框架個(gè)性化定制,下面我...
摘要:第四章安全管理制度發(fā)布第十條安全管理制度必須以正式文件的形式發(fā)布施行。第十一條安全管理制度由信息安全管理小組制訂,信息安全領(lǐng)導(dǎo)小組審批發(fā)布。第二十條安全管理制度的修改與廢止須經(jīng)信息安全領(lǐng)導(dǎo)組織審批確認(rèn),信息安全管理部門備案。 字?jǐn)?shù) 3610閱讀 760評(píng)論 0贊 3《xxxx安全管理制度匯編》****制度管理辦法****文...
摘要:本章目標(biāo)基于項(xiàng)目搭建可以站外請(qǐng)求訪問(wèn)的跨域資源服務(wù)器。允許所有的請(qǐng)求域名訪問(wèn)我們的跨域資源,可以固定單條或者多條內(nèi)容,如,只有百度可以訪問(wèn)我們的跨域資源。 CORS(Cross-Origin Resource Sharing)跨域資源共享,是一個(gè)W3C標(biāo)準(zhǔn),它允許瀏覽器向跨域服務(wù)器發(fā)送Ajax請(qǐng)求,打破了Ajax只能訪問(wèn)本站內(nèi)的資源限制,CORS在很多地方都有被使用,微信支付的JS支付...
摘要:本文將分享軟件基本用法及文件進(jìn)程注冊(cè)表查看,這是一款微軟推薦的系統(tǒng)監(jiān)視工具,功能非常強(qiáng)大可用來(lái)檢測(cè)惡意軟件。可以幫助使用者對(duì)系統(tǒng)中的任何文件注冊(cè)表操作進(jìn)行監(jiān)視和記錄,通過(guò)注冊(cè)表和文件讀寫的變化,有效幫助診斷系統(tǒng)故障或發(fā)現(xiàn)惡意軟件病毒及木馬。 ...
摘要:本章目標(biāo)根據(jù)項(xiàng)目定制參數(shù)狀態(tài)并了解的裝載過(guò)程以及實(shí)現(xiàn)方式。創(chuàng)建測(cè)試控制器創(chuàng)建名為的控制器并添加數(shù)據(jù)提交的方法,具體代碼如下所示表單提交控制器恒宇少年碼云裝載參數(shù)測(cè)試教師名稱, 在國(guó)內(nèi)企業(yè)開(kāi)發(fā)項(xiàng)目中大多數(shù)都已經(jīng)偏向Spring家族式的開(kāi)發(fā)風(fēng)格,在前幾年國(guó)內(nèi)項(xiàng)目都是以Structs2作為Web開(kāi)發(fā)的主導(dǎo),不過(guò)由于近幾年發(fā)生的事情確實(shí)讓開(kāi)發(fā)者對(duì)它失去了以往的信心。與此同時(shí)Spring家族發(fā)布...
閱讀 2666·2021-11-23 09:51
閱讀 1651·2021-11-22 13:54
閱讀 2789·2021-11-18 10:02
閱讀 948·2021-08-16 10:57
閱讀 3563·2021-08-03 14:03
閱讀 1879·2019-08-30 15:54
閱讀 3535·2019-08-23 14:39
閱讀 607·2019-08-23 14:26