|
在過去,我會(huì)經(jīng)常向你展示 EasyMock 是什么和怎樣使用它測(cè)試你的Java應(yīng)用?;谶@個(gè)目的,我將創(chuàng)建一個(gè)簡(jiǎn)單的股票程序并使用 JUnit 和 EasyMock 庫(kù)測(cè)試。
在開始之前,讓我們先理解一下使用 EasyMock 的需求。加入,你在創(chuàng)建一個(gè)Android 移動(dòng)應(yīng)用用來獲取用戶股票檔案。你的應(yīng)用需要使用股票市場(chǎng)服務(wù)從正式服務(wù)器來檢索股票價(jià)格(例如納斯達(dá)克)。
當(dāng)你開始測(cè)試代碼的時(shí)候,你也許不會(huì)想要去使用真實(shí)股票市場(chǎng)服務(wù)器來獲取股票價(jià)格。相反,你也許希望來些虛擬價(jià)格數(shù)據(jù)。所以你需要模擬股票市場(chǎng)服務(wù)然后返回虛擬數(shù)據(jù),而不去訪問真實(shí)服務(wù)器。
EasyMock 就是用來干這事的 -- 幫你模擬接口。你可以預(yù)定義一些模擬對(duì)象的行為,然后在測(cè)試代碼時(shí)使用模擬這些對(duì)象。因?yàn)槟汴P(guān)心的是測(cè)試你的代碼邏輯而不是外在服務(wù)和對(duì)象。因此。
為了使之清晰,請(qǐng)看一下下面的代碼摘要:
1 | StockMarket marketMock = EasyMock.createMock(StockMarket.class); |
2 | EasyMock.expect(marketMock.getPrice("EBAY")).andReturn(42.00); |
3 | EasyMock.replay(marketMock); |
第一行,我們要求 EasyMock 創(chuàng)建一個(gè)服務(wù)于 StockMarket 接口的模擬對(duì)象。然后第二行,我們定義了這個(gè)虛擬對(duì)象的行為--例如當(dāng)getPrice()對(duì)象被調(diào)用并傳遞 “EBAY” 參數(shù)時(shí),模擬對(duì)象將返回 42.00 .然后我們調(diào)用 replay() 方法時(shí),將使模擬對(duì)象備用。
這樣就差不錯(cuò)關(guān)聯(lián)好了 EasyMock 的上下文了和它的基本使用。接下來將深入我們的證劵應(yīng)用。
注意:點(diǎn)擊此處下載 Github 上的源碼
證卷應(yīng)用
我們的證券應(yīng)用非常簡(jiǎn)單。有一個(gè) Stock 類來存儲(chǔ)股票名和數(shù)量,Portfolio 類來保存股票列表。Portfolio 類有一個(gè)方法用來計(jì)算證券的總價(jià)格。我們的類用 StockMarket 對(duì)象來檢索股票價(jià)格。當(dāng)測(cè)試我們的代碼時(shí),我們將使用 EasyMock 來模擬StockMarket。
Stock.java
01 | package com.veerasundar.easymock; |
08 | public Stock(String name, int quantity) { |
10 | this.quantity = quantity; |
13 | public String getName() { |
17 | public void setName(String name) { |
21 | public int getQuantity() { |
25 | public void setQuantity(int quantity) { |
26 | this.quantity = quantity; |
StockMarket.java
用來模擬股票市場(chǎng)服務(wù)的接口。它包含一個(gè)通過給定股票名返回價(jià)格的方法。
1 | package com.veerasundar.easymock; |
3 | public interface StockMarket { |
4 | public Double getPrice(String stockName); |
Portfolio.java
該對(duì)象包含了 Stock 對(duì)象列表和一個(gè)計(jì)算證券總價(jià)格的方法。它使用 StockMarket 對(duì)象來檢索股票價(jià)格。但是硬編碼依賴不是好的實(shí)踐,我們不應(yīng)該在此就初始化 stockMarket 對(duì)象,我們應(yīng)該在使用測(cè)試代碼的時(shí)候注入進(jìn)來。
01 | package com.veerasundar.easymock; |
03 | import java.util.ArrayList; |
06 | public class Portfolio { |
09 | private StockMarket stockMarket; |
11 | private List<Stock> stocks = new ArrayList<Stock>(); |
17 | public Double getTotalValue() { |
19 | for (Stock stock : this.stocks) { |
20 | value += (stockMarket.getPrice(stock.getName()) * stock |
26 | public String getName() { |
30 | public void setName(String name) { |
34 | public List<Stock> getStocks() { |
38 | public void setStocks(List<Stock> stocks) { |
42 | public void addStock(Stock stock) { |
46 | public StockMarket getStockMarket() { |
50 | public void setStockMarket(StockMarket stockMarket) { |
51 | this.stockMarket = stockMarket; |
至此,我們便完成了整個(gè)應(yīng)用的編碼,接下來我們將測(cè)試 Portfolio.getTotalValue() 方法,因?yàn)槟鞘俏覀兊臉I(yè)務(wù)邏輯所在。
用 JUnit 與 EasyMock 測(cè)試 Portfolio 應(yīng)用
PortfolioTest.java
01 | package com.veerasundar.easymock.tests; |
03 | import junit.framework.TestCase; |
05 | import org.easymock.EasyMock; |
06 | import org.junit.Before; |
09 | import com.veerasundar.easymock.Portfolio; |
10 | import com.veerasundar.easymock.Stock; |
11 | import com.veerasundar.easymock.StockMarket; |
13 | public class PortfolioTest extends TestCase { |
15 | private Portfolio portfolio; |
16 | private StockMarket marketMock; |
20 | portfolio = new Portfolio(); |
21 | portfolio.setName("Veera's portfolio."); |
22 | marketMock = EasyMock.createMock(StockMarket.class); |
23 | portfolio.setStockMarket(marketMock); |
26 | <a href="http://my.oschina.net/test45" target="_blank" rel="nofollow">@Test</a> |
27 | public void testGetTotalValue() { |
34 | Stock ebayStock = new Stock("EBAY", 2); |
35 | portfolio.addStock(ebayStock); |
36 | assertEquals(84.00, portfolio.getTotalValue()); |
正如你所看到的,在 setUp() 調(diào)用時(shí)我們創(chuàng)建新的 Portfolio 對(duì)象。然后我們調(diào)用 EasyMock 要求為 StockMarket 接口創(chuàng)建一個(gè)模擬對(duì)象。然后我們使用 Portfolio.setStockMarket() 方法將這個(gè)對(duì)象注入到 Portfolio 對(duì)象。
在 @Tes t方法,我們使用以下代碼定義模擬對(duì)象的行為:
1 | EasyMock.expect(marketMock.getPrice("EBAY")).andReturn(42.00); |
2 | EasyMock.replay(marketMock); |
這樣一來,當(dāng) getPrice() 方法帶有 “EBAY” 的參數(shù)被調(diào)用的時(shí)候,將會(huì)返回42.00。
然后我們創(chuàng)建了一個(gè)數(shù)量為2的 ebayStock 股票,并將其添加到我們的 Portfolio 中。將我們?cè)O(shè)置 EBAY 價(jià)格為 42.00 時(shí),我們便知道股票的總價(jià)格為 84.00(2*42.00)。在最后一行,我們使用 assertEquals() 進(jìn)行了同樣的聲明。
如果 getTotalValue() 中代碼不出錯(cuò)的話,以上測(cè)試應(yīng)該會(huì)成功,否則測(cè)試將會(huì)失敗。
結(jié)論
以上便是如果使用 EasyMock 庫(kù)模擬外部服務(wù)/對(duì)象以及在測(cè)試代碼中使用的示例,EasyMock 能做的遠(yuǎn)不止我在上面展示的,點(diǎn)擊這里了解更多關(guān)于 EasyMock 的信息。
原文鏈接 / OSChina.NET 原創(chuàng)翻譯
|