初步認識JUnit

初步認識JUnitjava

  目前大多數的基於Java的企業應用軟件,確定少不了單元測試,程序員經過編寫單元測試來驗證本身程序的有效性;管理者經過持續自動的執行單元測試和分析單元測試覆蓋率來確保軟件自己的質量。能夠說單元測試和集成測試在軟件開發整個流程中佔有舉足輕重的地位。程序員

    單元測試,是指對軟件中的最小可測試單元進行檢查和驗證。單元測試不是爲了證實程序是對的,而是證實程序沒有錯。Java經常使用的單元測試框架有JUnit,TestNG,還有些MOCK框架,這裏咱們只來說述JUnit。web

JUnit            

JUnit的兩種版本是JUnit 3.8和JUnit 4,前者使用反射,後者使用反射和註解。spring

例子:
Calculator
 1 package com.shop.web.test;  2 public class Calculator {  3     private static double result = 0.0;  4     public void add(double num) {  5         result = result + num;  6  }  7     public void substract(double num) {  8         result = result - num;  9  } 10     public void multiply(double num) { 11         result = result * num; 12  } 13     public void divide(double num) { 14         if (num != 0) { 15             result = result / num; 16         } else { 17             result = result; 18  } 19  } 20     // 清零
21     public void clear() { 22         result = 0; 23  } 24     public double getResult() { 25         return result; 26  } 27 }

 CalculatorTest.java數據庫

 1 package com.shop.web.test;
 2 import junit.framework.TestCase;
 3 public class CalculatorTest extends TestCase {
 4     private static Calculator calculator = new Calculator();
 5     
 6     @Override
 7     protected void setUp() throws Exception {
 8         System.out.println("JUnit initialize the fixture state by overriding setup ");
 9         calculator.clear();
10     }
11     @Override
12     protected void tearDown() throws Exception {
13         System.out.println("JUnit clean-up after a test by overriding tearDown ");
14         calculator.clear();
15     }
16     public void testAdd() {
17         System.out.println("add result:" + calculator.getResult());
18         calculator.add(10.1);
19         assertEquals(10.1, calculator.getResult());
20     }
21     public void testSubstract() {
22         System.out.println("substract result:" + calculator.getResult());
23         calculator.add(10.1);
24         calculator.substract(2);
25         assertEquals(8.1, calculator.getResult());
26     }
27     public void testMultiply() {
28         System.out.println("multiply result:" + calculator.getResult());
29         calculator.add(12);
30         calculator.multiply(12);
31         assertEquals(144.0, calculator.getResult());
32     }
33     public void testDivide() {
34         System.out.println("divide result:" + calculator.getResult());
35         calculator.add(12);
36         calculator.divide(12);
37         assertEquals(1.0, calculator.getResult());
38     }
39 }

 綠條表明程序沒有錯誤apache

 

使用JUnit3.8          
須要知足以下原則:
一、測試方法使用test做爲方法名的前綴(JUnit設計 用反射找到以test開頭的方法)
二、測試方法必須使用public void 進行修飾,不能帶任何的參數
三、測試類和目標源代碼的類應該位於同一個包下面,即包名應該一致
四、新建一個源代碼目錄來存放咱們的測試代碼,即源代碼和測試代碼分開
五、測試方法中間必須能夠獨立測試,測試方法之間不能有任何的依賴關係
 
測試類必須繼承TestCase:
下面是TestCase的文檔說明,junit.framework.TestCase
1 public abstract class TestCase extends Assert implements Test
2         A test case defines the fixture to run multiple tests.
3         To define a test case
4         1) implement a subclass of TestCase
5         2) define instance variables that store the state of the fixture
6         3) initialize the fixture state by overriding setUp
7         4) clean-up after a test by overriding tearDown.
8         Each test runs in its own fixture so there can be no side effects among test runs
一、測試類經過重寫 TestCase的setUp()方法,用來初始化測試方法,即在每個測試方法執行以前執行;
二、測試類經過重寫 TestCase的tearDown()方法,用來清理測試方法產生的垃圾,即在每個測試方法執行以後執行;
如:執行例子計算器test
 1 JUnit initialize the fixture state by overriding setup 
 2 add result:0.0
 3 JUnit clean-up after a test by overriding tearDown 
 4 JUnit initialize the fixture state by overriding setup 
 5 substract result:0.0
 6 JUnit clean-up after a test by overriding tearDown 
 7 JUnit initialize the fixture state by overriding setup 
 8 multiply result:0.0
 9 JUnit clean-up after a test by overriding tearDown 
10 JUnit initialize the fixture state by overriding setup 
11 divide result:0.0
12 JUnit clean-up after a test by overriding tearDown 

 

使用JUnit4.1            
須要知足以下原則:
一、@Test
與JUnit 3.8.1不一樣,在JUnit 4.1中再也不強制要求方法名以test開頭,而是容許隨意命名,前提是沒有繼承TestCase,不然註解就不起做用了,其次只要符合Java的命名規範就行,但測試用例必須以@Test註解。
多個@Test沒有明確的執行順序,4.11版本MethodSorters能夠定義執行順序,若是你想要改變test的執行順序,那麼你能夠簡單的在test類上加以個註解@FixMethodOrder 而且指定一個合適的MethodSorters
   @FixMethodOrder(MethodSorters.JVM) : 根據JVM返回的順序來決定test方法的執行順序。每次測試這個順序可能都不同
  @FixMethodOrder(MethodSorters.NAME_ASCENDING) : 根據test方法名按照字典順序升序排序
二、@Before和@After
JUnit3.8.1中的setUp和tearDown這兩個方法,分別使用@Before和@After來進行註解,前者在每一個測試方法開始以前執行,多用來作初始化;後者在每一個測試方法完成以後執行,多用來清理資源。 註解必須用在public方法。
三、@BeforeClass和@AfterClass
JUnit 4.1還提供了@BeforeClass和@AfterClass註解,功能與@Before和@After相似,但前者是用在全部用例執行以前作初始化、以後作清理,然後者是在每一個用例執行以前作初始化、以後作清理。註解必須用在public static方法
注意: 前提是沒有繼承TestCase,不然註解就不起做用了,就必須使用test開頭的方法。
 1 public class CalculatorTest4 {
 2     private static Calculator calculator = new Calculator();
 3     
 4     @Before
 5     public void setUp() throws Exception {
 6         System.out.println("JUnit initialize the fixture state by overriding setup ");
 7         calculator.clear();
 8     }
 9     @After
10     public void tearDown() throws Exception {
11         System.out.println("JUnit clean-up after a test by overriding tearDown ");
12         calculator.clear();
13     }
14     @Test
15     public void add() {
16         System.out.println("add result:" + calculator.getResult());
17         calculator.add(10.1);
18         assertEquals(10.1, calculator.getResult());
19     }

 四、@Test(expected=*.class)
在JUnit4.0以前,對錯誤的測試,咱們只能經過fail來產生一個錯誤,並在try塊裏面assertTrue(true)來測試。如今,經過@Test元數據中的expected屬性。expected屬性的值是一個異常的類型,用來檢查拋出預期異常。json

1 @Test(expected=ArithmeticException.class)
2     public void divide(){
3         int i = 2/0;
4     }

五、@Test(timeout=xxx):
該元數據傳入了一個時間(毫秒)給測試方法,
若是測試方法在制定的時間以內沒有運行完,則測試也失敗。mybatis

@Test(timeout=1)
    public void count(){
        for (int i = 0; i < 1000000000; i++) {
            System.out.println(i);
        }
    }

 

六、@ignore:
該元數據標記的測試方法在測試中會被忽略。當測試的方法尚未實現,或者測試的方法已通過時,或者在某種條件下才能測試該方法(好比須要一個數據庫聯接, 而在本地測試的時候,數據庫並無鏈接),那麼使用該標籤來標示這個方法。同時,你能夠爲該標籤傳遞一個String的參數,來代表爲何會忽略這個測試 方法。好比:@lgnore(「該方法尚未實現」),在執行的時候,僅會報告該方法沒有實現,而不會運行測試方法。
1 @Ignore("此方法如今不須要")
2 @Test
3 public void ignore(){
4 System.out.println("不須要");
5 }

 

Spring整合JUnit          app

 Junit測試Spring能夠很方便的進行。 框架

用到jar包:spring-test-xxx.jar,junit4的jar。

須要註解 @RunWith、@ContextConfiguration

  @RunWith如:   @RunWith(SpringJUnit4ClassRunner.class)   //表示繼承了SpringJUnit4ClassRunner

  @ContextConfiguration如: 用來加載Spring配置文件,@ContextConfiguration(locations = {"classpath:applicationContext-mybatis.xml",……"})

注意:(1)若是spring配置文件applicationContext.xml在classpath路徑下,即一般的src目錄下,這樣加載配置文件,用classpath前綴。

     (2)可是在web項目中,有些人喜歡把spring配置文件applicationContext.xml放在WEB-INF目錄下,這裏不是classpath目錄。這種狀況能夠按以下方式配置:用file前綴,指定配置文件的絕對路徑。貌似這種方式不是很友好。 如:locations = { "file:D:\\workspace\\webproxy\\src\\main\\resources\\" + "applicationContext.xml" }

完整代碼以下:

package com.shop.web.test;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.shop.web.entity.ShopUser;
import com.shop.web.service.ShopUserService;
import com.shop.web.util.DateUtil;
/**
 * service、dao層的測試類
 * @author ces
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)//表示繼承了SpringJUnit4ClassRunner類 
@ContextConfiguration(locations = {"classpath:applicationContext-mybatis.xml","classpath:applicationContext-service.xml","classpath:applicationContext-transaction.xml"})
public class ShopControllerTest {
    
    private static Logger logger = Logger.getLogger(ShopControllerTest.class);
    
    @Resource
    private ShopUserService shopUserService;
    
    @Transactional
    @Test
    public void getShopUserById(){
        ShopUser shopUser = new ShopUser();
        shopUser.setUserid(6);
        shopUser.setUsername("zhangsan");
        shopUser.setPassword("333");
        shopUser.setCreateTime(Long.parseLong(DateUtil.getString(new Date(), DateUtil.YMDHMS)));
        try {
            shopUserService.insertSelective(shopUser);
            int i = 2/0;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("ShopControllerTest" + e);
        }
        
        logger.info(JSON.toJSONString("*********"));
    }
}
相關文章
相關標籤/搜索