easyMock原理簡述

2021-07-16 07:28:39 字數 3660 閱讀 7758

public

inte***ce

calculator

以上是乙個計算器介面,用於計算加法,假設現在我們的合作夥伴還沒有開發好這個加法的實現類,但是我們約定了這個加法器如果開發好的時候,會有一些表現,這個時候,我們要測試,該怎麼做呢。乙個簡單的辦法是,自己實現乙個簡單的實現類,返回寫死的結果。如下

public

class

calculatorimpl

implements

calculator

return

0; }

}

然後測試的時候,我們這樣幹

assert.assertequals(calculator.add(1,2),3);
如果我們要測試各種場景,我們就在**實現類中,新增各種場景,這些場景只是簡單的校驗引數,並沒有實際的業務邏輯。這無疑是個好辦法。可是這個方法有個缺點,就是每次都需要自己去單獨實現乙個類,這個很麻煩。而mock正是為了解決這個問題。

mock解決的問題是,提供乙個快速簡單的方法,用於書寫偽裝的業務邏輯。減少了我們為了新增測試用例而新寫乙個類的成本,我們來看使用mock的乙個示例

@test

public

void

test()

easymock提供了乙個更為簡易的方式,用於我們生產測試樣例的錄入。

簡單解釋一下上面的**

1. 建立乙個calculator的實現類的例項。

2. 記錄乙個測試樣例

3. 記錄完成,開始重放測試樣例

4. 測試

我相信大家如果光看**是很容易理解easymock的使用的,但是仔細看,可能會發現一些奇怪的地方,比如下面這段

easymock.expect(calculator.add(2,4)).andreturn(5);
**的語言是,如果add的入參為(2,4)則返回5.關鍵的問題是calculator.add(2,4)實際上應該不會返回任何東西,而且即使是有返回值,expect方法拿到返回值,也不可能通過返回值拿到入參,所以實際上如果要通過expect方法拿到入參實際上是不可能的,而且實際情況easymock也不是這樣做的。

public

static

iexpectationsetter***pect(t value)

可以看到easymock的expect方法,實際上並沒有使用入參。

實際上,在這裡easymock使用了動態**的技術。使用objectmethodsfilter**了實際的呼叫方法,

public

final object invoke(object proxy, method method, object args) throws throwable

if (hashcodemethod.equals(method))

if (tostringmethod.equals(method))

if (finalizemethod.equals(method))

return delegate.invoke(proxy, method, args);

}

並且通過**類,獲取入參。然後通過andreturn的方法,設定返回值。通過上述步驟來組裝乙個完整的請求呼叫。

有了上面簡單的知識,我們就能開始愉快地使用easymock了。如下所示

easymock.expect(calculator.add(2,4)).andreturn(5);

easymock.expect(calculator.add(2,4)).andreturn(8);

有的時候,我們有這樣的需求,我們希望第一次呼叫的時候,能有乙個結果,第二次使用的時候能有第二種不同的結果。這個時候我們就需要使用如上的使用方式,對於add(2,4)的情況使用兩次andreturn。但是實際上easymock提供了一種更為聰明的鏈式呼叫方式如下。

easymock.expect(calculator.add(2,4)).andreturn(5).andreturn(8);

easymock.replay(calculator);

assert.assertequals(calculator.add(2,4),5);

assert.assertequals(calculator.add(2,4),8);

當我們使用api的時候,可以多想想,為什麼api要這般設計,這樣多思考,才能學會更多。easymock在每次記錄之後,都需要顯示的呼叫replay告知,現在開始重放。我們來思考一下這個replay過程能否省略。

replay是否可以省略

假設我們要省略replay,站在語義分析的角度,一次呼叫分為 入參 - 返回結果 兩個主體,如果我們約定andreturn為語句的結尾,那麼就已經表達了完整的語義。我們來看最簡單的場景。

easymock.expect(calculator.add(2,4)).andreturn(5);

assert.assertequals(calculator.add(2,4),5);

假設我們要實現上述功能,我只需要有乙個map結構的資料,就好了。在eaysmock的階段,寫入map,map的key為函式入參,value為函式返回結果。然後當我們第二次呼叫函式的時候,我們從map中讀取資料返回。這樣上面的問題就完美解決了。

事實上,如果我們對入參的返回的返回值要去唯一的時候,我們確實可以這樣做,但是如果我們希望,乙個入參組合,每次呼叫的返回結果不同的時候,這個時候就不能這麼做了。例如

easymock.expect(calculator.add(2,4)).andreturn(5);

easymock.expect(calculator.add(2,4)).andreturn(8);

這個時候,第二次呼叫add(2,4)的時候,根本無法知曉,是要新增一種返回情況,還是一次真實呼叫。所以如果我們希望,我們可以對同乙個入參組合,返回多次不同的結果,那麼我們需要明確當前,我們應該對map做寫入,還是應該對map做讀取。所以replay的價值在於告訴easymock當前是讀取狀態,不要在寫入了,以後每次呼叫都是直接讀表中的值了。

資料結構

easymock用於儲存入參和返回結果的組合,使用了在arraylist中巢狀arraylist的方式,

如下**,

easymock.expect(calculator.add(1,3)).andreturn(4).andreturn(5);

easymock.expect(calculator.add(2,4)).andreturn(5).andreturn(8);

easymock.expect(calculator.add(1,3)).andreturn(4);

儲存時的資料結構,大概如下圖所示

key值為入參的組合,value為返回值的列表,會有乙個post指明,當前用到的返回值。

VXGI原理簡述

1.光柵化三角麵片場景 只有和三角麵片相交的體素會有值 color,normal 生成場景中opaque物體的體素形式 使用clipmap,這樣也沒有tree那麼麻煩了 2.類似forward shading 一樣渲染一下場景,得到物體表面收到的光照,從而得到體素反射出的intensity 3.在每...

https原理簡述

為什麼要使用https?因為http協議下,資料都是明文傳輸的,容易被截獲 修改 https實現原理 概要 通過非對稱加密進行互動協商獲得對稱加密演算法與金鑰,使用協商獲得的加密演算法與秘鑰對互動資料加密 4 伺服器接收瀏覽器發來的資料之後要做以下的操作 5 瀏覽器解密並計算握手訊息的hash,如果...

Jsonp 原理簡述

瀏覽器因為安全問題而有乙個同源策略,不允許跨域請求資料。但是 js 指令碼資源和資源還是被允許跨域請求的。在 web 開發中,遇到要跨域請求 json 資料時,可以用 jsonp 的方式來繞過瀏覽器的同源策略。現在,已經有很多任務具將 jsonp 封裝,如 jquery vue 等等。那麼封裝起來的...