單元測試&反射機制(未完結)

我是廿六啊發表於2020-11-11
單元測試

單元測試是指程式猿寫的測試程式碼給自己的類中的方法進行預期正確性的驗證

單元測試一旦寫好了這些測試程式碼,就可以一直使用,可以實現一定程度上的自動化驗證

單元測試一般是要使用框架進行

單元測試的經典框架:Junit

Junit是什麼?

  • Junit是Java語言編寫的第三方單元測試框架
  • Junit框架的方案可以幫助我們方便且快速的測試我們程式碼的正確性

單元測試概念

  • 單元:在Java,一個類就是一個單元
  • 單元測試:程式設計師用Junit編寫的一小段程式碼,用來對某個方法進行功能測試或業務邏輯測試。

Junit單元測試框架的作用:

  • 用來對類中的方法功能進行有目的的測試,以保證程式的正確性和穩定性
  • 能夠獨立的測試某個方法或者所有方法的預期正確性

框架一般是jar包的形式,jar包裡面都是class檔案

測試類的命名規範
  • 以Test開頭,以業務類類名結尾,使用駝峰式命名規範
測試類的注意事項:
  • 必須是public修飾的,沒有返回值,沒有引數
  • 必須使註解@Test修飾
/**Junit常用註解(Junit 4.xxxx版本)
    * @Test 測試方法!
    * @Before:用來修飾例項方法,該方法會在每一個測試方法執行之前執行一次。
    * @After:用來修飾例項方法,該方法會在每一個測試方法執行之後執行一次。
    * @BeforeClass:用來靜態修飾方法,該方法會在所有測試方法之前只執行一次。
    * @AfterClass:用來靜態修飾方法,該方法會在所有測試方法之後只執行一次。

   開始執行的方法:初始化資源。
   執行完之後的方法:釋放資源。

Junit常用註解(Junit5.xxxx版本)
    * @Test 測試方法!
    * @BeforeEach:用來修飾例項方法,該方法會在每一個測試方法執行之前執行一次。
    * @AfterEach:用來修飾例項方法,該方法會在每一個測試方法執行之後執行一次。
    * @BeforeAll:用來靜態修飾方法,該方法會在所有測試方法之前只執行一次。
    * @AfterAll:用來靜態修飾方法,該方法會在所有測試方法之後只執行一次。
例子
package com.fudao._01單元測試;

import org.junit.*;

public class UserServiceTest {
    UserService userService;
    // @Before:用來修飾例項方法,該方法會在每一個測試方法執行之前執行一次。
    @Before
    public void before(){
        userService = new UserService();
        System.out.println("===before===");

    }
    // @After:用來修飾例項方法,該方法會在每一個測試方法執行之後執行一次。
    @After
    public void after(){
        System.out.println("===after===");
    }

    // @BeforeClass:用來靜態修飾方法,該方法會在所有測試方法之前只執行一次。
    @BeforeClass
    public static void beforeClass(){
        System.out.println("===beforeClass===");
    }

    // @AfterClass:用來靜態修飾方法,該方法會在所有測試方法之後只執行一次。
    @AfterClass
    public static void afterClass(){
        System.out.println("===afterClass===");
    }


    /**
     * 測試方法的要求:
     *  1.必須public修飾
     *  2.沒有返回值沒有引數
     *  3. 必須使註解@Test修飾
     */
    @Test
    public void testLogin(){
//        UserService userService = new UserService();
        String rs = userService.login("admin","123456");
        // 斷言預期結果的正確性。
        /**
         * 引數一:測試失敗的提示資訊。
         * 引數二:期望值。
         * 引數三:實際值
         */
        // public static void assertEquals(String message, Object expected, Object actual)
        
        Assert.assertEquals("登入業務功能方法有錯誤,請檢查!","success",rs);
    }

    @Test
    public void testChu(){
//        UserService userService = new UserService();
        userService.chu(10 , 0);
    }
}
反射

反射是java獨有的技術,是java技術顯著的特點

反射是指對於任何一個類,在執行的時候 都可以直接得到這個類的全部成份

  • 在執行時,可以直接得到這個類的構造器物件Constructor
  • 在執行時,可以直接得到這個類的成員變數Field
  • 在執行時,可以直接得到這個類的成員方法物件Method

反射的核心思想和關鍵就是得到:編譯以後的class檔案物件

反射提供了一個Class型別,就是可以得到編譯以後的Class類物件

Class c = HelloWorld.class;

注意:反射是工作在執行時的技術,因為只有執行之後才會有class檔案物件

Class:位元組碼檔案的型別

Constructor:構造器的型別

Field:成員變數的型別

Method:方法的型別

反射技術的第一步永遠是先得到Class類物件:三種方式 獲取

  1. 類名.class
  2. 通過類的物件.getClass()方法
  3. Class.forName(“類的全限名”)

Class類的方法:

String getSimoleName(); 獲取類名字串:類名

String getName() 獲得類全名:包名+類名

例子
public class ReflectDemo01 {
    public static void main(String[] args) throws Exception {
        // 反射的第一步永遠是先得到類的Class檔案物件: 位元組碼檔案。
        // 1.類名.class
        Class c1 = Student.class;
        System.out.println(c1);

        // 2.物件.getClass()
        Student swk = new Student();
        Class c2 = swk.getClass();
        System.out.println(c2);

        // 3.Class.forName("類的全限名")
        // 直接去載入該類的class檔案。
        Class c3 = Class.forName("com.fudao._03反射_獲取Class類物件.Student");
        System.out.println(c3);

        System.out.println(c1.getSimpleName()); // 獲取類名本身(簡名)
        System.out.println(c1.getName()); // 獲取類的全限名
        // Student s1 = (Student) c1.newInstance(); // 呼叫無引數構造器得到物件,被淘汰了!

    }

}

反射中Class型別獲取構造器提供了很多的API:
1. Constructor getConstructor(Class… parameterTypes)
根據引數匹配獲取某個構造器,只能拿public修飾的構造器,幾乎不用!
2. Constructor getDeclaredConstructor(Class… parameterTypes)
根據引數匹配獲取某個構造器,只要申明就可以定位,不關心許可權修飾符,建議使用!
3. Constructor[] getConstructors()
獲取所有的構造器,只能拿public修飾的構造器。幾乎不用!!太弱了!
4. Constructor[] getDeclaredConstructors()
獲取所有申明的構造器,只要你寫我就能拿到,無所謂許可權。建議使用!!

小結:
獲取類的全部構造器物件: Constructor[] getDeclaredConstructors()
– 獲取所有申明的構造器,只要你寫我就能拿到,無所謂許可權。建議使用!!
獲取類的某個構造器物件:Constructor getDeclaredConstructor(Class… parameterTypes)
– 根據引數匹配獲取某個構造器,只要申明就可以定位,不關心許可權修飾符,建議使用!

例子
public class TestStudent {
    // 1. getConstructors:
    // 獲取全部的構造器:只能獲取public修飾的構造器。
    // Constructor[] getConstructors()
    @Test
    public void getConstructors(){
        // a.反射第一步先得到Class類物件
        Class c = Student.class ;
        // b.getConstructors():定位全部構造器,只能拿public修飾的!
        Constructor[] cons = c.getConstructors();
        // c.遍歷這些構造器
        for (Constructor con : cons) {
            System.out.println(con.getName()+"===>"+con.getParameterCount());
        }
    }

    // 2.getDeclaredConstructors():
    // 獲取全部的構造器:只要你敢寫,這裡就能拿到,無所謂許可權是否可及。
    @Test
    public void getDeclaredConstructors(){
        // a.反射第一步先得到Class類物件
        Class c = Student.class ;
        // b.getDeclaredConstructors():定位全部構造器,只要申明瞭就可以拿到
        Constructor[] cons = c.getDeclaredConstructors();
        // c.遍歷這些構造器
        for (Constructor con : cons) {
            System.out.println(con.getName()+"===>"+con.getParameterCount());
        }
    }

    // 3.getConstructor(Class... parameterTypes)
    // 獲取某個構造器:只能拿public修飾的某個構造器
    @Test
    public void getConstructor() throws Exception {
        // a.反射第一步先得到Class類物件
        Class c = Student.class ;
        // b.getConstructor():定位某個構造器,根據引數匹配,只能拿public修飾的!
        // Constructor con = c.getConstructor(); // 報錯!
        Constructor con = c.getConstructor(String.class  , int.class); // 有引數的!!
        // c.構造器名稱和引數
        System.out.println(con.getName()+"===>"+con.getParameterCount());
    }

    // 4.getDeclaredConstructor
    // 獲取某個構造器:只要你敢寫,這裡就能拿到,無所謂許可權是否可及。
    @Test
    public void getDeclaredConstructor() throws Exception {
        // a.反射第一步先得到Class類物件
        Class c = Student.class ;
        // b.getDeclaredConstructor():定位某個構造器,根據引數匹配,只要申明瞭就可以獲取
        Constructor con = c.getDeclaredConstructor(); // 可以拿到!定位無引數構造器!
        //Constructor con = c.getDeclaredConstructor(String.class  , int.class); // 有引數的!!
        // c.構造器名稱和引數
        System.out.println(con.getName()+"===>"+con.getParameterCount());
    }
}

相關文章