99偷拍视频精品区一区二,口述久久久久久久久久久久,国产精品夫妇激情啪发布,成人永久免费网站在线观看,国产精品高清免费在线,青青草在线观看视频观看,久久久久久国产一区,天天婷婷久久18禁,日韩动漫av在线播放直播

走進JavaWeb技術世界11:單元測試框架Junit

微信公眾號【黃小斜】大廠程序員,互聯(lián)網(wǎng)行業(yè)新知,終身學習踐行者。關注后回復「Java」、「Python」、「C++」、「大數(shù)據(jù)」、「機器學習」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經(jīng)」、「計算機基礎」、「LeetCode」 等關鍵字可以獲取對應的免費學習資料。 
JUnit你不知道的那些事兒
轉(zhuǎn)自 老劉 碼農(nóng)翻身 2016-02-24
話說有一次Eric Gamma 坐飛機的時候偶遇Kent Beck(對,就是極限編程和TDD的發(fā)起人) ,  兩位大牛見面寒暄過以后就覺得很無聊了。
旅途漫漫,干點啥好呢。
Kent Beck當時力推測試驅(qū)動開發(fā),  但是沒有一個工具或者框架能讓大家輕松愉快的寫測試,并且自動的運行測試。
兩人勾兌了一下:不如自己挽起袖子寫一個, 于是兩人就在飛機上結(jié)對編程 ,  等到飛機的時候,一個劃時代的單元測試工具就新鮮出爐了,這就是JUnit:
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
JUnit當然是用Java寫的, 其他語言一看, 這東西好, 咱也搞一套, 于是就有了一大批工具,統(tǒng)稱xUnit
NUnit (針對.Net 平臺) ,  CUnit (針對C語言) , CppUnit(針對C++語言), PyUnit (針對Python), PHPUnit, OCUnit, DUnit, JSUnit ......
超級大牛出馬,親自敲出來的代碼自然非同凡響, 它的設計簡直就是使用設計模式的典范:
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
更牛的是, 他們是以一種叫做“模式生成架構(gòu)”的方法來創(chuàng)建JUnit的, 換句話說,就是從零應用模式, 然后一個接一個, 直到你獲取最終的系統(tǒng)架構(gòu):
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
我第一次看到這種方式, 真是驚為天人,  我知道代碼要向模式進行重構(gòu), 還從來沒聽過由模式來構(gòu)建系統(tǒng)!
但一想到Eric Gamma的背景, 就沒有什么可驚訝的了, 因為Eric Gamma 實際上是劃時代的書籍《設計模式:可復用面向?qū)ο筌浖A》四位合著者(稱為GoF,Gang of Four)之一
這本書的經(jīng)典地位就不用說了, 像JUnit繁衍出來的xUnit一樣, 這本書也有很多的“繁衍品”, 例如
《Head First Degisn Pattern》 , 《設計模式解析》,《大話設計模式》。。。。
JUnit超級流行,幾乎是事實上的Java 單元測試和TDD的工具標準, 有人選擇了GitHub上最熱的三門語言Java,Ruby和Javascript , 對每個語言分析了1000個項目,找出了最常用的組件,可以看到JUnit 以30.7%并列第一
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
所以JUnit已經(jīng)變成了程序員必備的技能, 不會JUnit就太Out了。

Junit入門

1、什么是Junit4

JUnit4是一個易學易用的Java單元測試框架,一般我們在寫完一段代碼或一個方的時候,都要測試一下這段代碼和這個方法的邏輯是不是正確,輸入一定的數(shù)據(jù),返回的數(shù)據(jù)是不是我們想要的結(jié)果,即我們在寫單個業(yè)務代碼針對結(jié)果進行測試。這時Junit就派上了大用場了。

2、為何使用Junit4

也許有的初學者會說,項目完成之后測試不行嗎?如果你要這么想的話,那就了,因為隨著你代碼的增加,你牽扯到的模塊和項目中的邏輯就會越來越多,這樣測試起來就會非常的麻煩,而且容易出錯。Junit看起來是增加了代碼量,可是它可以大大的減少后期的測試時間,提升代碼的質(zhì)量,讓代碼更易于維護。

3、Junit4的快速入門

下載并導入Junitjar包:
首先得需要去網(wǎng)上下載一個Junit4的一個jar包,保存到自己本地電腦里面打開myEclipse新建一個Java項目,通過右擊項目-->Build Path --->Configure Build Path -->Add External JARs--->找到自己剛保存的jar路徑,點擊OK就可以啦
創(chuàng)建測試目錄:
接下來就要為我們的測試建立特殊的路徑,這個特殊特殊在哪里呢,因為我們的測試代碼要單獨保存不能與源代碼進行混淆,到項目結(jié)束后可以直接把它刪除,而且不會對項目造成影響。怎么創(chuàng)建呢:右擊項目名稱--->new---->suorce folder--->輸入你想要的測試文件名點擊OK就可以啦。
接下來我們得在項目中的src目錄下創(chuàng)建一個包,注意這兒的包名和test里面的包名要保持一致,在我們src的包下寫我們項目的邏輯方法,在test的報下寫我們的測試方法,結(jié)構(gòu)如圖所示,
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
image.png
下面我們來寫一段簡單的邏輯代碼進行測試演練
package com.junit;public class method_junti {
    public int add(int a, int b) {
        return a + b;
    }
    public int subtract(int a, int b) {
        return a - b;
    }
    public int multiply(int a, int b) {
        return a * b;
    }
    public int division(int a, int b) {
        return a / b;
    }}
方法很簡單,就是一般的加減乘除,下面我們就可以進行測試了,怎么測試呢: 在我們的測試目錄下新建測試類junit_test,然后定義測試方法。代碼如下:
package com.junit;import static org.junit.Assert.*;import org.junit.Test;public class junit_test {
    
    //測試方法必須有@test;
    //該測試方法必須由public void修飾,沒有返回值;
    //該方法不帶任何參數(shù);
    //新建一個源代碼測試文件單獨存放測試代碼;
    //測試類的包和被測試類的包保持一致;
    //測試方法間互相獨立沒有任何依賴;
    @Test    public void testAdd(){
        
        assertEquals(4, new method_junti().add(3, 0));
    }
    
    @Test    public void testSubtract(){
        assertEquals(3, new method_junti().subtract(6, 3));
    }
    
    @Test    public void testMultiply(){
        assertEquals(6, new method_junti().multiply(6, 1));
    }
    
    @Test    public void testDivision(){
        assertEquals(6, new method_junti().division(6, 1));
    }}
下面來講解一下assertEquals()這個函數(shù),它的第一個參數(shù)是你預期的一個結(jié)果,第二個參數(shù)使我們想測試的函數(shù),這個函數(shù)我們要通過先new出函數(shù)所在的類,然后通過類來調(diào)用方法,方法里面的參數(shù)就是你在寫該方法是傳進來的參數(shù)。在這里最好在你需要測試的方法的前面加上test,這樣的話就會比較規(guī)范一些
寫完之后你可以點擊測試類,然后在點擊run as,再點擊Junit test,你就能在彈出的窗口中看到你的測試結(jié)果,它會提示你失敗的個數(shù)和錯誤的個數(shù)。如果你只想測試一個方法怎么辦呢,在你創(chuàng)建的測試類的下面還有目錄,列表里面的會列出你所有的測試方法,你就可以右擊你想測試的方法,然后run as ---> junit test,測試成功后就會看到一個綠色的條,結(jié)果如圖:
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
image.png
在這里如果我們每一個方法都要自己手動的敲出它的測試方法,在這里我們只是簡單的測試了幾個方法,在項目中如果我們有很多的方法需要測試,一個一個的敲的話會有些浪費時間了,這里給大家介紹一個快速生成測試方法的一個方法: 點擊src下的method_junit.java--->右擊new--->看看后面的提示框中有么有Junit test case,如果沒有的話點擊other,在提示框中輸入Junit 就會出現(xiàn)--->在彈出的對話框中找到Source folder,點擊后面的Browse將其改為含有test的那個目錄,這里有些可能會提示名字重復,把下面的 Name改改就行--->點擊next--->你會看到method_junit里面的所有法,這時候你就可以選中它們,成成測試方法如下:
package com.junit;import static org.junit.Assert.*;import org.junit.Test;public class method_juntiTest2 {
    @Test    public void testAdd() {
        fail("Not yet implemented");
    }
    @Test    public void testSubtract() {
        fail("Not yet implemented");
    }
    @Test    public void testMultiply() {
        fail("Not yet implemented");
    }
    @Test    public void testDivision() {
        fail("Not yet implemented");
    }}
再把里面fail后面的語句刪了就可以寫你想測試的東西呢!

4、junit測試失敗的兩種情況:

在前面的情況中我們都是測試的是成功的例子,但是Junit的作用只是測試的方法里的返回數(shù)據(jù)是不是正確的,但是在數(shù)據(jù)返回正確的情況下我們未必是正確的,就比如如果你要求的是長方形的面積,但是你用的是周長公式,當你在測試的時候他也會給你測試成功,得到預期的結(jié)果,也就是說我們的測試用例對于邏輯錯誤是無能為力的
測試失敗的情況一 當我們預期值和程序執(zhí)行的結(jié)果不一樣的時候就會測試失敗: 比如我們上面的測試加法函數(shù)的方法:
@Testpublic void testAdd(){
      assertEquals(3, new method_junti().add(3, 0));}
如果把預期結(jié)果3,改為4,就會測試失敗,failure的后面就會出現(xiàn)一個1,提示一個測試失敗,運行時就能看到,這個應該不難理解。如果你仔細觀察的話,下面還會有相關的提示,如圖所示:
走進JavaWeb技術世界11:單元測試框架Junit
添加描述
image.png
測試失敗情況二: 下面我們在來測試除法:
@Testpublic void testDivision(){
    assertEquals(6, new method_junti().division(6, 1));}
如果在這里把除數(shù)改為0,會出現(xiàn)什么情況呢:后面的提示框中的error數(shù)就會變1;提示有一個錯誤。于是我們得出下面的兩種情況:
1、failure一般由單元測試使用的斷言方法判斷失敗所引起的,這表示測試點發(fā)現(xiàn)了問題,也就是說程序輸出的結(jié)果和預期的不一樣 2、error是由代碼異常引起的,他可能是由于測試代碼本身的錯誤,也可能是被測試代碼中隱藏的一個bug

5、Junit的運行流程:

首先我們先在test包下的com.junit新建一個junit case,和并且直接命名junit_case。在創(chuàng)建的時候把setUpBeforeClass(),tearDownAfterClass(),setUp() ,tearDown() 選上就會得到下面的代碼:
package com.junit;import org.junit.After;import org.junit.AfterClass;import static org.junit.Assert.*;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;public class Junit_case {
    @BeforeClass    public static void setUpBeforeClass() throws Exception {
    }
    @AfterClass    public static void tearDownAfterClass() throws Exception {
    }
    @Before    public void setUp() throws Exception {
    }
    @After    public void tearDown() throws Exception {
    }
    @Test    public void test() {
        fail("Not yet implemented");
    }}
下面我們在每個方法中輸入一句簡單的輸出語句,看看他們的運行狀態(tài),如下:
package com.junit;import static org.junit.Assert.*;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;public class Junit_test1 {
    
    /* 1、BeforeClass修飾的方法會在所有方法被調(diào)用前執(zhí)行
     * 而且該方法是靜態(tài)的,所以當測試類被加載后接著就執(zhí)行它
     * 在內(nèi)存中它只會存在一份,適合加載配置文件
     * 2、AfterClass修飾的方法用來對資源的清理,如關閉數(shù)據(jù)庫的連接
     * befoer和after修飾的方法在每個test修飾的方法執(zhí)行前會被各執(zhí)行一次,假如有兩個
     * test文件,before和after會被各執(zhí)行兩次;
     * */
    @BeforeClass    public static void setUpBeforeClass() throws Exception {
        System.out.println("this is beforeclass");
    }
    @AfterClass    public static void tearDownAfterClass() throws Exception {
        System.out.println("this is afterclass");
    }
    @Before    public void setUp() throws Exception {
        System.out.println("this is before");
    }
    @After    public void tearDown() throws Exception {
        System.out.println("this is after");
    }
    @Test    public void test1() {
        System.out.println("this is test1");
    }}
如果運行上面的代碼,就會得到下面的結(jié)果

6、junit的常用注解:

上面我已經(jīng)講解了@test,@BeforeClass,@AfterClass,@Before,@After這些注解的詳解可見這位仁兄的博客,下面提供相關地址: http://blog.csdn.net/zixiao217/article/details/52951679 對于@test,他除了將一個普通的方法修飾為測試方法外,還可以處理異常,設置超時。下面來對test的異常處理做講解test有兩個參數(shù):expected和timeout,即異常處理和設置超時如果對我們上面的除數(shù)為0的那個方法進行異常處理,那么我們就可以看到代碼能夠正常,測試通過,代碼如下:
@Test(expected=ArithmeticException.class)public void testDivision(){
     assertEquals(6, new method_junti().division(6, 0));}
在測試一些對性能有要求的方法中設置超時是很有必要的,它可以檢測你的代碼能否在這個 時間段內(nèi)運行出結(jié)果,設置方法如下:
@Test(timeout=2000)//單位是毫秒
 public void testWhile(){
    while(true){
        System.out.println("run forever");
    }}
@Ignore:在test方法上加上該修飾,測試的時候就會不執(zhí)行該測試方法; @RunWith可以更改測試運行器;我們除了使用junit提供的測試運行器之外,還可以自定義 我們的運行器,只要繼承org.junit.runner.Runner 代碼如下:
import static org.junit.Assert.*;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;@RunWith(Suite.class)@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})public class SuitTest {
    
    public void test(){
        /*
         * 由于在開發(fā)的項目中,測試的類很多,一個一個運行很浪費時間,于是可以寫一個測試
         * 套件把所有需要測試的類組合在一起測試運行
         * 1、寫一個測試入口,這個類不含其它的方法;
         * 2、更改測試運行器@RunWith(Suite.class)
         * 3、將要測試的類作為數(shù)組放在@Suite.SuiteClasses({})中;
         */
        
    }}

7、junit的參數(shù)設置

在上面的測試中,我們對一個方法都是只測試了一組數(shù)據(jù),可是在真正的項目中,一組數(shù)據(jù)往往是不夠的,我們需要很多組數(shù)據(jù),如果每一組數(shù)組寫一個測試方法的話那可把我們的工作人員累死了!這時我們可以使用參數(shù)設置來解決這個問題。 代碼如下:
package com.junit;import static org.junit.Assert.*;import java.util.Arrays;import java.util.Collection;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameters;@RunWith(Parameterized.class)public class ParameterTest {
    //聲明變量存放預期值和測試數(shù)據(jù);
    int expected=0;
    int input1=0;
    int input2=0;
    
    @Parameters    public static Collection<Object[]> test(){
    
        return Arrays.asList(new Object[][]{
                {3,1,2},
                {4,2,2}
            });     
    }
    public ParameterTest(int expected,int input1,int input2){
        this.expected=expected;
        this.input1=input1;
        this.input2=input2;
    }
    @Test    public void testAdd(){
        assertEquals(expected, new method_junti().add(input1, input2));
    }   }
我們需要測試多組數(shù)據(jù),那么我們就需要用到數(shù)組來存放多組數(shù)據(jù),這里用Arrays.asList來接收。

聊聊單元測試在SpringMVC中的運用

轉(zhuǎn)自  杜琪
遇到問題多思考、多查閱、多驗證,方能有所得,再勤快點樂于分享,才能寫出好文章。

一、單元測試

1. 定義與特點

單元測試(unit testing) :是指對軟件中的最小可測試單元進行檢查和驗證。
這個定義有點抽象,這里舉幾個單元測試的特性,大家感受一下:一般是一個函數(shù)配幾個單元測試、單元測試不應該依賴外部系統(tǒng)、單元測試運行速度很快、單元測試不應該造成測試環(huán)境的臟數(shù)據(jù)、單元測試可以重復運行。

2. 優(yōu)點

單元測試使得我們可以放心修改、重構(gòu)業(yè)務代碼,而不用擔心修改某處代碼后帶來的副作用。
單元測試可以幫助我們反思模塊劃分的合理性,如果一個單元測試寫得邏輯非常復雜、或者說一個函數(shù)復雜到無法寫單測,那就說明模塊的抽象有問題。
單元測試使得系統(tǒng)具備更好的可維護性、具備更好的可讀性;對于團隊的新人來說,閱讀系統(tǒng)代碼可以從單元測試入手,一點點開始后熟悉系統(tǒng)的邏輯。

3. 本文要解決的痛點

  1. 單測何時寫? 如果你的團隊在堅持TDD的風格,那就是在編碼之前寫;如果沒有,也不建議在全部業(yè)務代碼編寫完成之后再開始補單元測試。單元測試比較(最)合適的時機是:一塊業(yè)務邏輯寫完后,跟著寫幾個單元測試驗證下。
  2. 單測怎么寫? 分層單測:數(shù)據(jù)庫操作層、中間件依賴層、業(yè)務邏輯層,各自的單元測試各自寫,互相不要有依賴。
  3. 單測運行太慢?
  • dao層測試,使用H2進行測試,做獨立的BaseH2Test、獨立的test-h3-applicationContext.xml,只對dao的測試
  • service層測試,依賴mockito框架,使用@RunWith(MockitoJUnitRunner.class)注解,就無需加載其他spring bean,具體用法
  • 對于依賴外部的中間件(例如redis、diamond、mq),在處理單測的時候要注意分開加載和測試,尤其是與dao的測試分開

二、Spring項目中的單元測試實踐

我們基于 unit-test-demo 這個項目進行單元測試的實踐。

1. dao層單元測試

最開始寫單測的時候,要連著DEV的數(shù)據(jù)庫,這時候會有兩個煩惱:網(wǎng)絡有問題的時候單測運行不通過、數(shù)據(jù)庫里造成臟數(shù)據(jù)的時候會導致應用程序異常。這里我們選擇H2進行DAO層的單元測試。有如下幾個步驟:
  • 在resources下新建目錄h3,存放schema.sql和data-prepare-user.sql文件,前者用于保存建表語句,后者用于準備初始數(shù)據(jù)
  • test-data-source.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/jdbc
       http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
    <!-- 初始化數(shù)據(jù)表結(jié)構(gòu) -->
    <jdbc:initialize-database data-source="dataSource">
        <jdbc:script location="classpath:h3/schema.sql" encoding="UTF-8"/>
        <jdbc:script location="classpath:h3/data-prepare-*.sql" encoding="UTF-8"/>
    </jdbc:initialize-database>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <property name="url" value="${user.jdbc.url}"/>
        <property name="username" value="${user.jdbc.username}"/>
        <property name="password" value="${user.jdbc.password}"/>
        <!-- 連接池初始連接數(shù) -->
        <property name="initialSize" value="3"/>
        <!-- 允許的最大同時使用中(在被業(yè)務線程持有,還沒有歸還給druid) 的連接數(shù) -->
        <property name="maxActive" value="30"/>
        <!-- 允許的最小空閑連接數(shù),空閑連接超時踢除過程會最少保留的連接數(shù) -->
        <property name="minIdle" value="3"/>
        <!-- 從連接池獲取連接的最大等待時間 5 秒-->
        <property name="maxWait" value="5000"/>
        <!-- 強行關閉從連接池獲取而長時間未歸還給druid的連接(認為異常連接)-->
        <property name="removeAbandoned" value="true"/>
        <!-- 異常連接判斷條件,超過180 秒 則認為是異常的,需要強行關閉 -->
        <property name="removeAbandonedTimeout" value="180"/>
        <!-- 從連接池獲取到連接后,如果超過被空閑剔除周期,是否做一次連接有效性檢查 -->
        <property name="testWhileIdle" value="true"/>
        <!-- 從連接池獲取連接后,是否馬上執(zhí)行一次檢查 -->
        <property name="testOnBorrow" value="false"/>
        <!-- 歸還連接到連接池時是否馬上做一次檢查 -->
        <property name="testOnReturn" value="false"/>
        <!-- 連接有效性檢查的SQL -->
        <property name="validationQuery" value="SELECT 1"/>
        <!-- 連接有效性檢查的超時時間 1 秒 -->
        <property name="validationQueryTimeout" value="1"/>
        <!-- 周期性剔除長時間呆在池子里未被使用的空閑連接, 10秒一次-->
        <property name="timeBetweenEvictionRunsMillis" value="10000"/>
        <!-- 空閑多久可以認為是空閑太長而需要剔除 30 秒-->
        <property name="minEvictableIdleTimeMillis" value="30000"/>
        <!-- 是否緩存prepareStatement,也就是PSCache,MySQL建議關閉 -->
        <property name="poolPreparedStatements" value="false"/>
        <property name="maxOpenPreparedStatements" value="-1"/>
        <!-- 是否設置自動提交,相當于每個語句一個事務 -->
        <property name="defaultAutoCommit" value="true"/>
        <!-- 記錄被判定為異常的連接 -->
        <property name="logAbandoned" value="true"/>
        <!-- 網(wǎng)絡讀取超時,網(wǎng)絡連接超時 -->
        <property name="connectionProperties" value="connectTimeout=1000;socketTimeout=3000"/>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/>
        <property name="typeAliasesPackage" value="org.learnjava.dq.core.dal.bean"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.learnjava.dq.core.dal.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean></beans>
  • test-h3-applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 激活自動代理功能 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <!-- spring容器啟動時,靜態(tài)配置替換 -->
    <context:property-placeholder location="classpath*:*.properties" ignore-unresolvable="true"/>
    <context:component-scan base-package="org.learnjava.dq.core.dal.dao"/>
    <import resource="test-data-sources.xml"/></beans>
  • UserInfoDAOTest 這個文件是DAO層單元測試的主要內(nèi)容,我只寫了一個,讀者朋友可以下載代碼自己練習,把剩余的幾個寫了。
PS:這里我們只有一個DAO,所以spring容器加載就放在這個文件里了,如果DAO多的話,建議抽出一個BaseH2Test文件,這樣所有的DAO單元測試只需要加載一次spring容器。
package org.learnjava.dq.core.dal.dao;import org.junit.Test;import org.junit.runner.RunWith;import org.learnjava.dq.core.dal.bean.UserInfoBean;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.Date;import javax.annotation.Resource;import static org.junit.Assert.*;/**
 * 作用:
 * User: duqi
 * Date: 2017/6/24
 * Time: 09:33
 */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:test-h3-applicationContext.xml")public class UserInfoDAOTest {
    @Resource    private UserInfoDAO userInfoDAO;
    @Test    public void saveUserInfoBean() throws Exception {
        UserInfoBean userInfoBean = new UserInfoBean();
        userInfoBean.setUserId(1003L);
        userInfoBean.setNickname("wangwu");
        userInfoBean.setMobile("18890987675");
        userInfoBean.setSex(1);
        userInfoBean.setUpdateTime(new Date());
        userInfoBean.setCreateTime(new Date());
        int rows = userInfoDAO.saveUserInfoBean(userInfoBean);
        assertEquals(1, rows);
    }
    @Test    public void updateUserInfoBean() throws Exception {
    }
    @Test    public void getUserInfoBeanByUserId() throws Exception {
    }
    @Test    public void getUserInfoBeanByMobile() throws Exception {
    }
    @Test    public void listUserInfoBeanByUserIds() throws Exception {
    }
    @Test    public void removeUserInfoBeanByUserId() throws Exception {
    }}

2. service層單元測試

  • Mockito Mocktio是一個非常易用的mock框架。開發(fā)者可以依靠Mockito提供的簡潔的API寫出漂亮的單元測試。
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.
  • UserInfoManagerImplTest 單元測試,不應該依賴于DAO層的執(zhí)行邏輯是否正確【否則就是集成測試】,需要假設DAO的行為是什么樣子,然后再看本層的邏輯是否正確。 這里使用@RunWith(MockitoJUnitRunner.class)修飾當前的單元測試類,如果有多個單元測試類的話,可以考慮抽出一個基礎的BaseBizTest類。
package org.learnjava.dq.biz.manager.impl;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.learnjava.dq.biz.domain.UserInfo;import org.learnjava.dq.biz.manager.UserInfoManager;import org.learnjava.dq.core.dal.bean.UserInfoBean;import org.learnjava.dq.core.dal.dao.UserInfoDAO;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.MockitoAnnotations;import org.mockito.runners.MockitoJUnitRunner;import static org.junit.Assert.*;import static org.mockito.Mockito.*;/**
 * 作用:
 * User: duqi
 * Date: 2017/6/24
 * Time: 09:55
 */@RunWith(MockitoJUnitRunner.class)public class UserInfoManagerImplTest {
    @Mock //用于定義被Mock的組件
    private UserInfoDAO userInfoDAO;
    @InjectMocks //用于定義待測試的組件
    private UserInfoManager userInfoManager = new UserInfoManagerImpl();
    private UserInfo userInfoToSave;
    @Before    public void setUp() throws Exception {
        //用于初始化@Mock注解修飾的組件
        MockitoAnnotations.initMocks(this);
        userInfoToSave = new UserInfo();
        userInfoToSave.setMobile("18978760099");
        userInfoToSave.setUserId(7777L);
        userInfoToSave.setSex(1);
    }
    @Test    public void saveUserInfo_case1() throws Exception {
        //step1 準備數(shù)據(jù)和動作
        doReturn(1).when(userInfoDAO).saveUserInfoBean(any(UserInfoBean.class));
        //step2 運行待測試模塊
        Boolean res = userInfoManager.saveUserInfo(userInfoToSave);
        //step3 驗證測試結(jié)果
        assertTrue(res);
    }
    @Test    public void saveUserInfo_case2() throws Exception {
        //step1 準備數(shù)據(jù)和動作
        doReturn(0).when(userInfoDAO).saveUserInfoBean(any(UserInfoBean.class));
        //step2 運行待測試模塊
        Boolean res = userInfoManager.saveUserInfo(userInfoToSave);
        //step3 驗證測試結(jié)果
        assertFalse(res);
    }
    @Test    public void updateUserInfo() throws Exception {
    }
    @Test    public void getUserInfoByUserId() throws Exception {
    }
    @Test    public void getUserInfoByMobile() throws Exception {
    }
    @Test    public void listUserInfoByUserIds() throws Exception {
    }
    @Test    public void removeUserInfoByUserId() throws Exception {
    }}
  • Mockito要點
  • MockitoJUnitRunner:用于提供單元測試運行的容器環(huán)境
  • Mock:用于模擬待測試模塊中依賴的外部組件
  • InjectMock:用于標識待測試組件
  • org.mockito.Mockito.*:這個類里的方法可以用于指定Mock組件的預期行為,包括異常處理。

三、總結(jié)

  1. 單元測試的三個步驟
  • 準備數(shù)據(jù)、行為
  • 測試目標模塊
  • 驗證測試結(jié)果
  1. 除了本文中提到的Junit、Mockito、H2,還有很多其他的單元測試框架,例如 TestNG 、 spock 等。
  2. 在Java Web項目中,controller層一般不寫業(yè)務邏輯,也就沒有必要寫單元測試,但是如果要寫,也有辦法,可以參考我之前的文章: 在Spring Boot項目中使用Spock框架 。
  3. 單元測試代碼也是線上代碼,要和業(yè)務代碼一樣認真對待,也需要注意代碼和測試數(shù)據(jù)的復用。

一位阿里 Java 工程師的技術小站。作者黃小斜,專注 Java 相關技術:SSM、SpringBoot、MySQL、分布式、中間件、集群、Linux、網(wǎng)絡、多線程,偶爾講點Docker、ELK,同時也分享技術干貨和學習經(jīng)驗,致力于Java全棧開發(fā)!(關注公眾號后回復”Java“即可領取 Java基礎、進階、項目和架構(gòu)師等免費學習資料,更有數(shù)據(jù)庫、分布式、微服務等熱門技術學習視頻,內(nèi)容豐富,兼顧原理和實踐,另外也將贈送作者原創(chuàng)的Java學習指南、Java程序員面試指南等干貨資源)

標題名稱:走進JavaWeb技術世界11:單元測試框架Junit
本文路徑:http://www.yijiale78.com/article22/joopjc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷手機網(wǎng)站建設小程序開發(fā)標簽優(yōu)化網(wǎng)站建設用戶體驗

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設