1. 程式人生 > >JMockit Mock 私有方法和私有屬性

JMockit Mock 私有方法和私有屬性

前面說過 JMockit 因身處前線,所以簡直無不可,本節例子演示 JMockit 怎麼 Mock 私有方法和私有屬性,示例雖然是靜態方法和屬性,但因採用的是反射手法,所以這種 Deencapsulation 的 Mock 手段同樣適用於公有的方法或屬性,無論是否靜態。

本文所用 JMockit 版本為 1.6, 可能網上所搜尋的方法與此有所不同,請注意 JMockit 版本差異。仍需重複一下,執行 JMockit 的例子 classpath 上必須讓 jmockit.jar 在 junit.jar 之前,或用 javaagent 引數來載入 jmockit.jar,並且 junit 要 4.8 及以上版本.

1. Mock 私有方法(非靜態類似)

package cc.unmi;

public class MyService {
    public static String fetchData(String name){
        System.out.println("call MyService.fetchData");
        return fetchDataFromDB(name);
    }
    
    private static String fetchDataFromDB(String name){
        throw new RuntimeException("Not implemented yet!"
);     } }

fetchDataFromDB 是私有靜態方法,正常測試的話肯定不過

package cc.unmi;

import mockit.Deencapsulation;
import mockit.Expectations;

import org.junit.Assert;
import org.junit.Test;

public class MyServiceTest {

    @Test
    public void testFetchData() {

        new Expectations(MyService.class) {
            {
                Deencapsulation.invoke(MyService.class, "fetchDataFromDB"
, "Unmi");                 result = "http://unmi.cc";             }         };         String actual = MyService.fetchData("Unmi");         Assert.assertEquals("http://unmi.cc", actual);     } }

這行

Deencapsulation.invoke(MyService.class, "fetchDataFromDB", "Unmi");

使用了反射的方式攔截了 MyService 的 fetchDataFromDB 方法,並非強設了它的返回值為  “http://unmi.cc”。關鍵是呼叫了 Deencapsulation.invoke() 方法,來看到這個類裡還有哪些方法:

jmockit-deencapsulation

看到上圖,我們必須要產生一些想法的,特別是 invoke 和 setField,以及它們的第一個引數可以是 Class,也可以是 Object,不難獲知的是我們能夠藉助於它來 Mocket 私有方法和屬性,不論它們是靜態還是非靜態的。

上面的測試用例可以見綠,輸出為:

call MyService.fetchData

如果把測試程式碼中的呼叫處改為

String actual = MyService.fetchData("Unmis");

測試將會失敗:

java.lang.RuntimeException: Not implemented yet! 
    at cc.unmi.MyService.fetchDataFromDB(MyService.java:10) 
    at cc.unmi.MyService.fetchData(MyService.java:6) 
    at cc.unmi.MyServiceTest.testFetchData(MyServiceTest.java:21) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    ................

對了,就是反射。受上面的點撥,怎麼 Mock 屬性已瞭然於心了,再行累述純為拉長篇幅,不妨

2. Mock 私有屬性(靜態亦類似)

package cc.unmi;

public class MyService {
    
    private String url = "";
    
    public String fetchData(String name){
        System.out.println("call MyService.fetchData");
        return this.url;
    }
}

欲 Mock 的是 url 屬性,從 fetchData 方法的 return url 可以檢測到 Mock 後的值

package cc.unmi;

import mockit.Deencapsulation;
import mockit.Expectations;

import org.junit.Assert;
import org.junit.Test;

public class MyServiceTest {

    @Test
    public void testFetchData() {
        final MyService service = new MyService();
        
        new Expectations() {
            {
                Deencapsulation.setField(service, "url", "http://unmi.cc");
            }
        };

        String actual = service.fetchData("Unmi");
        Assert.assertEquals("http://unmi.cc", actual);
    }
}

斷言成功,與 Mock 私有方法有所不同的是在 new Expectations() 的括號中可以留白了,也用不著設定 result 值了。

從資料上看 Deencapsulation 是後來引入的,原來好像是直接呼叫  Expectations 的 invoke, setField 方法來改變執行中的值。

記得當初我們用 @MockClass, @Mock, 再 Mockit.setUpMock() 三步曲來進行 Mock 操作,如今看來光 new Expectations() 這一招便可走遍天下。

相關推薦

JMockit Mock 私有方法私有屬性

前面說過 JMockit 因身處前線,所以簡直無不可,本節例子演示 JMockit 怎麼 Mock 私有方法和私有屬性,示例雖然是靜態方法和屬性,但因採用的是反射手法,所以這種 Deencapsulation 的 Mock 手段同樣適用於公有的方法或屬性,無論是否靜態。 本文所用 JMockit 版本為

python私有方法私有屬性屬性理解

__init__ out code 避免 col 系統 import name sizeof 私有屬性、方法——Python並沒有真正的私有化支持,但可用下劃線得到偽私有盡量避免定義以下劃線開頭的變量 (1)_xxx "單下劃線 " 開始的成員變量叫做保護變量

Python中私有方法私有屬性

Python 私有方法 私有屬性 1.私有方法和私有屬性私有方法只能在類內部被調用,不能被對象使用私有屬性只能在類內部使用,不能被對象使用 私有屬性只能在類內部使用,對象不能使用,但是,我們可以通過在類內部定義公有方法對私有屬性進行調用或修改,然後對象在調用這個公有方法使用。###私有屬性和私有方

python私有方法私有屬性

Python預設的成員函式和成員變數都是公開的,Python 私有屬性和方法沒有類似別的語言的public,private等關鍵詞來修飾。 在python中定義私有變數只需要在變數名或函式名前加上 "__"兩個下劃線,那麼這個函式或變數就會為私有的了宣告該方法為私有方法,不能在類的外部呼叫

為什麼說 Objective-C 沒有私有方法私有變數

首先,我們先來看一下私有的定義:私有是指只能夠在本類內部使用或訪問,但是不能在類的外部被訪問。 看起來好像沒有什麼問題,不過以下的幾種方式的確打破了上面的規則。 訪問私有方法 在 Objective-C 中,物件呼叫方法是以傳送訊息的形式實現的。所有方法的呼叫最終都會轉化為傳送訊息的形式,原型如下:

通過反射訪問任意類的私有方法屬性

 給出一個如下類: package test2; public class MathDemo {     private int m = 10;     private MathDemo(){     }     private int add(int a,i

Python的程序結構(2) -> 方法/Method -> 類實例方法私有方法抽象方法

模塊 魔術 程序 技術 pytho 將不 abs 保護 error 類實例方法、私有方法和抽象方法 Python中最常用的就是類實例方法,類似於屬性中的類實例屬性,同時,也存在與私有屬性類似方法,即私有方法,下面介紹這兩種常見的方法,以及一種特殊意義的類實例方法 -- 抽

python 類的私有變數私有方法介紹

版權宣告:博主原創文章,轉載請註明來源,謝謝合作!! https://mp.csdn.net/mdeditor/84438578 預設情況下,Python中的成員函式和成員變數都是公開的(public),在python中沒有類似public,private等關鍵詞來修飾成員

Java Reflection(七):私有變數私有方法

原文地址 作者: Jakob Jenkov 譯者:葉文海([email protected]) 內容索引 訪問私有變數 訪問私有方法 在通常的觀點中從物件的外部訪問私有變數以及方法是不允許的,但是Java反射機制可以做到這一點。使用這個功能並不困難,在進行單元測試時這個功能非常有效。

使用powerMockmockito模擬靜態方法私有方法

首先我們要匯入相應的包 <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artif

Java 反射建立類的例項物件(預設構造方法私有構造方法

反射之建立類的例項物件 通過反射可以建立Class<?>中”?”對應的型別的例項物件,眾所眾知,建立類物件,會呼叫構造方法,構造器可以有多個,預設構造方法,多引數構造方法等。 這裡演示,通過反射建立預設構造方法的例項物件,和帶引數的構造方法的例項

iOS開發私有變數私有方法

oc中有私有變數,沒有私有犯法,但是嚴格來說沒有絕對的私有變數和私有方法 私有變數: oc中提供了關鍵字@private來宣告私有變數,只允許本類訪問 私有方法: oc中沒有提供關鍵字來宣告私有方法,可以通過catogry的匿名類E

Java 私有變數私有方法

作者: Jakob Jenkov 譯者:葉文海([email protected]) 內容索引 訪問私有變數訪問私有方法 在通常的觀點中從物件的外部訪問私有變數以及方法是不允許的,但是 Java 反射機制可以做到這一點。使用這個功能並不困難,在進行單元測試時這個功能非常有效。本節會向你展示如何

利用java反射機制,實現對類的私有變數私有方法的訪問

記得有一句很有名的話:No reflection ,no frameworks 這一句短短的話道出了java 反射機制的強大。 java關於反射機制的包主要在java.lang.reflect中,structs,hibernate,spring等框架都是基於java的反射機制。 下面是一個關於利用j

python中的例項方法、靜態方法、類方法私有方法保護方法

例項方法: 例項方法顧名思義就是例項物件呼叫的方法,是最普遍最常用的類中的方法: class animal(object): def __init__(self): pass def talk(self):

Vue2.x源碼學習筆記-Vue靜態方法靜態屬性整理

temp next 技術 spa delet 結構 又是 靜態 https Vue靜態方法和靜態屬性,其實直接在瀏覽器中可以查看到的,如下 圈起來的是其靜態屬性,但是有的屬性對象中的屬性的值又是函數。未圈起來的則是函數。 其實它來自如下各個目錄下的js文件 // src

php中靜態方法靜態屬性的介紹

靜態屬性 size col 實例 生效 訪問類 都是 靜態 self 靜態分為兩個部分:靜態屬性和靜態方法 靜態的東西都是給類用的(包括類常量),非靜態的都是給對象用的 靜態屬性 在定義屬性的時候,使用關鍵字static修飾的屬性稱之為靜態屬性。 靜態方法 使用sta

python進階之類常用魔法方法魔法屬性

sdn 主程序 都是 執行 pre 直接 內部 __main__ == 前言 前面我們總結過了python的關鍵字、運算符、內置函數、語法糖等與python魔法方法之間的關系,現在我們更細一點,看看python的面向對象編程有哪些常用的魔法屬性和魔法方法。 魔法屬性 對於一

ES6 - 類的靜態方法靜態屬性

一、靜態方法 類的所有方法都定義在類的prototype屬性上面,所有類中定義的方法都會被例項繼承,如果在類方法前面加上static關鍵字就不會被例項繼承了。 靜態方法是直接通過類名來呼叫。 class Person{ constructor(name="xf",age){ t

十二、python學習之python高階二(property、魔法方法魔法屬性、多繼承多重繼承、閉包裝飾器)

一、property: 1.get/set方法: 1.1 隱藏實現細節:在使用物件時,儘量不要讓使用者直接操作物件中的屬性,這樣會帶來安全隱患。改進辦法,使用私有屬性。 1.2 提供精確的訪問控制:學習過 set/get方法,是專門來為類的私有屬性提供訪問介面。 1.