亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

使用 EasyMock 更輕松地進(jìn)行測(cè)試

系統(tǒng) 1859 0

測(cè)試驅(qū)動(dòng)開(kāi)發(fā)是軟件開(kāi)發(fā)的重要部分。如果代碼不進(jìn)行測(cè)試,就是不可靠的。所有代碼都必須測(cè)試,而且理想情況下應(yīng)該在編寫代碼之前編寫測(cè)試。但是,有些東西容易測(cè)試,有些東西不容易。如果要編寫一個(gè)代表貨幣值的簡(jiǎn)單的類,那么很容易測(cè)試把 $1.23 和 $2.8 相加是否能夠得出 $4.03,而不是 $3.03 或 $4.029999998。測(cè)試是否不會(huì)出現(xiàn) $7.465 這樣的貨幣值也不太困難。但是,如何測(cè)試把 $7.50 轉(zhuǎn)換為 €5.88 的方法呢(尤其是在通過(guò)連接數(shù)據(jù)庫(kù)查詢隨時(shí)變動(dòng)的匯率信息的情況下)?在每次運(yùn)行程序時(shí), amount.toEuros() 的正確結(jié)果都可能有變化。

答案是 mock 對(duì)象 。測(cè)試并不通過(guò)連接真正的服務(wù)器來(lái)獲取最新的匯率信息,而是連接一個(gè) mock 服務(wù)器,它總是返回相同的匯率。這樣就可以得到可預(yù)測(cè)的結(jié)果,可以根據(jù)它進(jìn)行測(cè)試。畢竟,測(cè)試的目標(biāo)是 toEuros() 方法中的邏輯,而不是服務(wù)器是否發(fā)送正確的值。(那是構(gòu)建服務(wù)器的開(kāi)發(fā)人員要操心的事)。這種 mock 對(duì)象有時(shí)候稱為 fake 。

mock 對(duì)象還有助于測(cè)試錯(cuò)誤條件。例如,如果 toEuros() 方法試圖獲取最新的匯率,但是網(wǎng)絡(luò)中斷了,那么會(huì)發(fā)生什么?可以把以太網(wǎng)線從計(jì)算機(jī)上拔出來(lái),然后運(yùn)行測(cè)試,但是編寫一個(gè)模擬網(wǎng)絡(luò)故障的 mock 對(duì)象省事得多。

mock 對(duì)象還可以測(cè)試類的行為。通過(guò)把斷言放在 mock 代碼中,可以檢查要測(cè)試的代碼是否在適當(dāng)?shù)臅r(shí)候把適當(dāng)?shù)膮?shù)傳遞給它的協(xié)作者??梢酝ㄟ^(guò) mock 查看和測(cè)試類的私有部分,而不需要通過(guò)不必要的公共方法公開(kāi)它們。

最后,mock 對(duì)象有助于從測(cè)試中消除依賴項(xiàng)。它們使測(cè)試更單元化。涉及 mock 對(duì)象的測(cè)試中的失敗很可能是要測(cè)試的方法中的失敗,不太可能是依賴項(xiàng)中的問(wèn)題。這有助于隔離問(wèn)題和簡(jiǎn)化調(diào)試。

EasyMock 是一個(gè)針對(duì) Java 編程語(yǔ)言的開(kāi)放源碼 mock 對(duì)象庫(kù),可以幫助您快速輕松地創(chuàng)建用于這些用途的 mock 對(duì)象。EasyMock 使用動(dòng)態(tài)代理,讓您只用一行代碼就能夠創(chuàng)建任何接口的基本實(shí)現(xiàn)。通過(guò)添加 EasyMock 類擴(kuò)展,還可以為類創(chuàng)建 mock。可以針對(duì)任何用途配置這些 mock,從方法簽名中的簡(jiǎn)單啞參數(shù)到檢驗(yàn)一系列方法調(diào)用的多調(diào)用測(cè)試。

EasyMock 簡(jiǎn)介

現(xiàn)在通過(guò)一個(gè)具體示例演示 EasyMock 的工作方式。清單 1 是虛構(gòu)的 ExchangeRate 接口。與任何接口一樣,接口只說(shuō)明實(shí)例要做什么,而不指定應(yīng)該怎么做。例如,它并沒(méi)有指定從 Yahoo 金融服務(wù)、政府還是其他地方獲取匯率數(shù)據(jù)。


清單 1. ExchangeRate

            import java.io.IOException;

public interface ExchangeRate {

    double getRate(String inputCurrency, String outputCurrency) throws IOException;

}
          

?

清單 2 是假定的 Currency 類的骨架。它實(shí)際上相當(dāng)復(fù)雜,很可能包含 bug。(您不必猜了:確實(shí)有 bug,實(shí)際上有不少)。


清單 2. Currency

            import java.io.IOException;

public class Currency {

    private String units;
    private long amount;
    private int cents;


    public Currency(double amount, String code) {
        this.units = code;
        setAmount(amount);
    }

    private void setAmount(double amount) {
        this.amount = new Double(amount).longValue();
        this.cents = (int) ((amount * 100.0) % 100);
    }

    public Currency toEuros(ExchangeRate converter) {
        if ("EUR".equals(units)) return this;
        else {
            double input = amount + cents/100.0;
            double rate;
            try {
                rate = converter.getRate(units, "EUR");
                double output = input * rate;
                return new Currency(output, "EUR");
            } catch (IOException ex) {
                return null;
            }
        }
    }

    public boolean equals(Object o) {
        if (o instanceof Currency) {
            Currency other = (Currency) o;
            return this.units.equals(other.units)
                    && this.amount == other.amount
                    && this.cents == other.cents;
        }
        return false;
    }

    public String toString() {
        return amount + "." + Math.abs(cents) + " " + units;
    }

}
          

?

Currency 類設(shè)計(jì)的一些重點(diǎn)可能不容易一下子看出來(lái)。匯率是從這個(gè)類 之外 傳遞進(jìn)來(lái)的,并不是在類內(nèi)部構(gòu)造的。因此,很有必要為匯率創(chuàng)建 mock,這樣在運(yùn)行測(cè)試時(shí)就不需要與真正的匯率服務(wù)器通信。這還使客戶機(jī)應(yīng)用程序能夠使用不同的匯率數(shù)據(jù)源。

清單 3 給出一個(gè) JUnit 測(cè)試,它檢查在匯率為 1.5 的情況下 $2.50 是否會(huì)轉(zhuǎn)換為 €3.75。使用 EasyMock 創(chuàng)建一個(gè)總是提供值 1.5 的 ExchangeRate 對(duì)象。


清單 3. CurrencyTest

            import junit.framework.TestCase;
import org.easymock.EasyMock;
import java.io.IOException;

public class CurrencyTest extends TestCase {

    public void testToEuros() throws IOException {
        Currency expected = new Currency(3.75, "EUR");
        ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);
        EasyMock.expect(mock.getRate("USD", "EUR")).andReturn(1.5);
        EasyMock.replay(mock);
        Currency actual = testObject.toEuros(mock);
        assertEquals(expected, actual);
    }

}
          

?

老實(shí)說(shuō),在我第一次運(yùn)行 清單 3 時(shí)失敗了,測(cè)試中經(jīng)常出現(xiàn)這種問(wèn)題。但是,我已經(jīng)糾正了 bug。這就是我們采用 TDD 的原因。

運(yùn)行這個(gè)測(cè)試,它通過(guò)了。發(fā)生了什么?我們來(lái)逐行看看這個(gè)測(cè)試。首先,構(gòu)造測(cè)試對(duì)象和預(yù)期的結(jié)果:

            Currency testObject = new Currency(2.50, "USD");
Currency expected = new Currency(3.75, "EUR");
          

?

這不是新東西。

接下來(lái),通過(guò)把 ExchangeRate 接口的 Class 對(duì)象傳遞給靜態(tài)的 EasyMock.createMock() 方法,創(chuàng)建這個(gè)接口的 mock 版本:

            ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);
          

?

這是到目前為止最不可思議的部分。注意,我可沒(méi)有編寫實(shí)現(xiàn) ExchangeRate 接口的類。另外, EasyMock.createMock() 方法絕對(duì)無(wú)法返回 ExchangeRate 的實(shí)例,它根本不知道這個(gè)類型,這個(gè)類型是我為本文創(chuàng)建的。即使它能夠通過(guò)某種奇跡返回 ExchangeRate ,但是如果需要模擬另一個(gè)接口的實(shí)例,又會(huì)怎么樣呢?

我最初看到這個(gè)時(shí)也非常困惑。我不相信這段代碼能夠編譯,但是它確實(shí)可以。這里的 “黑魔法” 來(lái)自 Java 1.3 中引入的 Java 5 泛型和動(dòng)態(tài)代理(見(jiàn) 參考資料 )。幸運(yùn)的是,您不需要了解它的工作方式(發(fā)明這些訣竅的程序員確實(shí)非常聰明)。

下一步同樣令人吃驚。為了告訴 mock 期望什么結(jié)果,把方法作為參數(shù)傳遞給 EasyMock.expect() 方法。然后調(diào)用 andReturn() 指定調(diào)用這個(gè)方法應(yīng)該得到什么結(jié)果:

            EasyMock.expect(mock.getRate("USD", "EUR")).andReturn(1.5);
          

?

EasyMock 記錄這個(gè)調(diào)用,因此知道以后應(yīng)該重放什么。

如果在使用 mock 之前忘了調(diào)用 EasyMock.replay() ,那么會(huì)出現(xiàn) IllegalStateException 異常和一個(gè)沒(méi)有什么幫助的錯(cuò)誤消息: missing behavior definition for the preceding method call

接下來(lái),通過(guò)調(diào)用 EasyMock.replay() 方法,讓 mock 準(zhǔn)備重放記錄的數(shù)據(jù):

            EasyMock.replay(mock);
          

?

這是讓我比較困惑的設(shè)計(jì)之一。 EasyMock.replay() 不會(huì)實(shí)際重放 mock。而是重新設(shè)置 mock,在下一次調(diào)用它的方法時(shí),它將開(kāi)始重放。

現(xiàn)在 mock 準(zhǔn)備好了,我把它作為參數(shù)傳遞給要測(cè)試的方法:


為類創(chuàng)建 mock

從實(shí)現(xiàn)的角度來(lái)看,很難為類創(chuàng)建 mock。不能為類創(chuàng)建動(dòng)態(tài)代理。標(biāo)準(zhǔn)的 EasyMock 框架不支持類的 mock。但是,EasyMock 類擴(kuò)展使用字節(jié)碼操作產(chǎn)生相同的效果。您的代碼中采用的模式幾乎完全一樣。只需導(dǎo)入 org.easymock.classextension.EasyMock 而不是 org.easymock.EasyMock 。為類創(chuàng)建 mock 允許把類中的一部分方法替換為 mock,而其他方法保持不變。

            Currency actual = testObject.toEuros(mock);
          

?

最后,檢查結(jié)果是否符合預(yù)期:

            assertEquals(expected, actual);
          

?

這就完成了。如果有一個(gè)需要返回特定值的接口需要測(cè)試,就可以快速地創(chuàng)建一個(gè) mock。這確實(shí)很容易。 ExchangeRate 接口很小很簡(jiǎn)單,很容易為它手工編寫 mock 類。但是,接口越大越復(fù)雜,就越難為每個(gè)單元測(cè)試編寫單獨(dú)的 mock。通過(guò)使用 EasyMock,只需一行代碼就能夠創(chuàng)建 java.sql.ResultSet org.xml.sax.ContentHandler 這樣的大型接口的實(shí)現(xiàn),然后向它們提供運(yùn)行測(cè)試所需的行為。

?


?

測(cè)試異常

mock 最常見(jiàn)的用途之一是測(cè)試異常條件。例如,無(wú)法簡(jiǎn)便地根據(jù)需要制造網(wǎng)絡(luò)故障,但是可以創(chuàng)建模擬網(wǎng)絡(luò)故障的 mock。

當(dāng) getRate() 拋出 IOException 時(shí), Currency 類應(yīng)該返回 null 。清單 4 測(cè)試這一點(diǎn):


清單 4. 測(cè)試方法是否拋出正確的異常

            public void testExchangeRateServerUnavailable() throws IOException {
   ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);
   EasyMock.expect(mock.getRate("USD", "EUR")).andThrow(new IOException());
   EasyMock.replay(mock);
   Currency actual = testObject.toEuros(mock);
   assertNull(actual);
}
          

?

這里的新東西是 andThrow() 方法。顧名思義,它只是讓 getRate() 方法在被調(diào)用時(shí)拋出指定的異常。

可以拋出您需要的任何類型的異常(已檢查、運(yùn)行時(shí)或錯(cuò)誤),只要方法簽名支持它即可。這對(duì)于測(cè)試極其少見(jiàn)的條件(例如內(nèi)存耗盡錯(cuò)誤或無(wú)法找到類定義)或表示虛擬機(jī) bug 的條件(比如 UTF-8 字符編碼不可用)尤其有幫助。

?


?

設(shè)置預(yù)期

EasyMock 不只是能夠用固定的結(jié)果響應(yīng)固定的輸入。它還可以檢查輸入是否符合預(yù)期。例如,假設(shè) toEuros() 方法有一個(gè) bug(見(jiàn)清單 5),它返回以歐元為單位的結(jié)果,但是獲取的是加拿大元的匯率。這會(huì)讓客戶發(fā)一筆意外之財(cái)或遭受重大損失。


清單 5. 有 bug 的 toEuros() 方法

            public Currency toEuros(ExchangeRate converter) {
    if ("EUR".equals(units)) return this;
    else {
        double input = amount + cents/100.0;
        double rate;
        try {
            rate = converter.getRate(units, "CAD");
            double output = input * rate;
            return new Currency(output, "EUR");
        } catch (IOException e) {
            return null;
        }
    }
}
          

?

但是,不需要為此編寫另一個(gè)測(cè)試。 清單 4 中的 testToEuros 能夠捕捉到這個(gè) bug。當(dāng)對(duì)這段代碼運(yùn)行清單 4 中的測(cè)試時(shí),測(cè)試會(huì)失敗并顯示以下錯(cuò)誤消息:

            "java.lang.AssertionError:
  Unexpected method call getRate("USD", "CAD"):
    getRate("USD", "EUR"): expected: 1, actual: 0".
          

?

注意,這并不是我設(shè)置的斷言。EasyMock 注意到我傳遞的參數(shù)不符合測(cè)試用例。

在默認(rèn)情況下,EasyMock 只允許測(cè)試用例用指定的參數(shù)調(diào)用指定的方法。但是,有時(shí)候這有點(diǎn)兒太嚴(yán)格了,所以有辦法放寬這一限制。例如,假設(shè)希望允許把任何字符串傳遞給 getRate() 方法,而不僅限于 USD EUR 。那么,可以指定 EasyMock.anyObject() 而不是顯式的字符串,如下所示:

            EasyMock.expect(mock.getRate(
       (String) EasyMock.anyObject(),
       (String) EasyMock.anyObject())).andReturn(1.5);
          

?

還可以更挑剔一點(diǎn)兒,通過(guò)指定 EasyMock.notNull() 只允許非 null 字符串:

            EasyMock.expect(mock.getRate(
        (String) EasyMock.notNull(),
        (String) EasyMock.notNull())).andReturn(1.5);
          

?

靜態(tài)類型檢查會(huì)防止把非 String 對(duì)象傳遞給這個(gè)方法。但是,現(xiàn)在允許傳遞 USD EUR 之外的其他 String 。還可以通過(guò) EasyMock.matches() 使用更顯式的正則表達(dá)式。下面指定需要一個(gè)三字母的大寫 ASCII String

            EasyMock.expect(mock.getRate(
        (String) EasyMock.matches("[A-Z][A-Z][A-Z]"),
        (String) EasyMock.matches("[A-Z][A-Z][A-Z]"))).andReturn(1.5);
          

?

使用 EasyMock.find() 而不是 EasyMock.matches() ,就可以接受任何包含三字母大寫子 String String

EasyMock 為基本數(shù)據(jù)類型提供相似的方法:

  • EasyMock.anyInt()
  • EasyMock.anyShort()
  • EasyMock.anyByte()
  • EasyMock.anyLong()
  • EasyMock.anyFloat()
  • EasyMock.anyDouble()
  • EasyMock.anyBoolean()

對(duì)于數(shù)字類型,還可以使用 EasyMock.lt(x) 接受小于 x 的任何值,或使用 EasyMock.gt(x) 接受大于 x 的任何值。

在檢查一系列預(yù)期時(shí),可以捕捉一個(gè)方法調(diào)用的結(jié)果或參數(shù),然后與傳遞給另一個(gè)方法調(diào)用的值進(jìn)行比較。最后,通過(guò)定義定制的匹配器,可以檢查參數(shù)的任何細(xì)節(jié),但是這個(gè)過(guò)程比較復(fù)雜。但是,對(duì)于大多數(shù)測(cè)試, EasyMock.anyInt() EasyMock.matches() EasyMock.eq() 這樣的基本匹配器已經(jīng)足夠了。

?


?

嚴(yán)格的 mock 和次序檢查

EasyMock 不僅能夠檢查是否用正確的參數(shù)調(diào)用預(yù)期的方法。它還可以檢查是否以正確的次序調(diào)用這些方法,而且只調(diào)用了這些方法。在默認(rèn)情況下,不執(zhí)行這種檢查。要想啟用它,應(yīng)該在測(cè)試方法末尾調(diào)用 EasyMock.verify(mock) 。例如,如果 toEuros() 方法不只一次調(diào)用 getRate() ,清單 6 就會(huì)失敗。


清單 6. 檢查是否只調(diào)用 getRate() 一次

            public void testToEuros() throws IOException {
    Currency expected = new Currency(3.75, "EUR");
    ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);
    EasyMock.expect(mock.getRate("USD", "EUR")).andReturn(1.5);
    EasyMock.replay(mock);
    Currency actual = testObject.toEuros(mock);
    assertEquals(expected, actual);
    EasyMock.verify(mock);
}
          

?

EasyMock.verify() 究竟做哪些檢查取決于它采用的操作模式:

  • Normal — EasyMock.createMock() :必須用指定的參數(shù)調(diào)用所有預(yù)期的方法。但是,不考慮調(diào)用這些方法的次序。調(diào)用未預(yù)期的方法會(huì)導(dǎo)致測(cè)試失敗。
  • Strict — EasyMock.createStrictMock() :必須以指定的次序用預(yù)期的參數(shù)調(diào)用所有預(yù)期的方法。調(diào)用未預(yù)期的方法會(huì)導(dǎo)致測(cè)試失敗。
  • Nice — EasyMock.createNiceMock() :必須以任意次序用指定的參數(shù)調(diào)用所有預(yù)期的方法。調(diào)用未預(yù)期的方法 不會(huì) 導(dǎo)致測(cè)試失敗。Nice mock 為沒(méi)有顯式地提供 mock 的方法提供合理的默認(rèn)值。返回?cái)?shù)字的方法返回 0 ,返回布爾值的方法返回 false 。返回對(duì)象的方法返回 null 。

檢查調(diào)用方法的次序和次數(shù)對(duì)于大型接口和大型測(cè)試更有意義。例如,請(qǐng)考慮 org.xml.sax.ContentHandler 接口。如果要測(cè)試一個(gè) XML 解析器,希望輸入文檔并檢查解析器是否以正確的次序調(diào)用 ContentHandler 中正確的方法。例如,請(qǐng)考慮清單 7 中的簡(jiǎn)單 XML 文檔:


清單 7. 簡(jiǎn)單的 XML 文檔

            <root>
  Hello World!
</root>
          

?

根據(jù) SAX 規(guī)范,在解析器解析文檔時(shí),它應(yīng)該按以下次序調(diào)用這些方法:

  1. setDocumentLocator()
  2. startDocument()
  3. startElement()
  4. characters()
  5. endElement()
  6. endDocument()

但是,更有意思的是,對(duì) setDocumentLocator() 的調(diào)用是可選的;解析器可以多次調(diào)用 characters() 。它們不需要在一次調(diào)用中傳遞盡可能多的連續(xù)文本,實(shí)際上大多數(shù)解析器不這么做。即使是對(duì)于清單 7 這樣的簡(jiǎn)單文檔,也很難用傳統(tǒng)的方法測(cè)試 XML 解析器,但是 EasyMock 大大簡(jiǎn)化了這個(gè)任務(wù),見(jiàn)清單 8:


清單 8. 測(cè)試 XML 解析器

            import java.io.*;
import org.easymock.EasyMock;
import org.xml.sax.*;
import org.xml.sax.helpers.XMLReaderFactory;
import junit.framework.TestCase;

public class XMLParserTest extends TestCase {

    private  XMLReader parser;

    protected void setUp() throws Exception {
        parser = XMLReaderFactory.createXMLReader();
    }

    public void testSimpleDoc() throws IOException, SAXException {
        String doc = "<root>\n  Hello World!\n</root>";
        ContentHandler mock = EasyMock.createStrictMock(ContentHandler.class);

        mock.setDocumentLocator((Locator) EasyMock.anyObject());
        EasyMock.expectLastCall().times(0, 1);
        mock.startDocument();
        mock.startElement(EasyMock.eq(""), EasyMock.eq("root"), EasyMock.eq("root"),
                (Attributes) EasyMock.anyObject());
        mock.characters((char[]) EasyMock.anyObject(),
                EasyMock.anyInt(), EasyMock.anyInt());
        EasyMock.expectLastCall().atLeastOnce();
        mock.endElement(EasyMock.eq(""), EasyMock.eq("root"), EasyMock.eq("root"));
        mock.endDocument();
        EasyMock.replay(mock);

        parser.setContentHandler(mock);
        InputStream in = new ByteArrayInputStream(doc.getBytes("UTF-8"));
        parser.parse(new InputSource(in));

        EasyMock.verify(mock);
    }
}
          

?

這個(gè)測(cè)試展示了幾種新技巧。首先,它使用一個(gè) strict mock,因此要求符合指定的次序。例如,不希望解析器在調(diào)用 startDocument() 之前調(diào)用 endDocument()

第二,要測(cè)試的所有方法都返回 void 。這意味著不能把它們作為參數(shù)傳遞給 EasyMock.expect() (就像對(duì) getRate() 所做的)。(EasyMock 在許多方面能夠 “欺騙” 編譯器,但是還不足以讓編譯器相信 void 是有效的參數(shù)類型)。因此,要在 mock 上調(diào)用 void 方法,由 EasyMock 捕捉結(jié)果。如果需要修改預(yù)期的細(xì)節(jié),那么在調(diào)用 mock 方法之后立即調(diào)用 EasyMock.expectLastCall() 。另外注意,不能作為預(yù)期參數(shù)傳遞任何 String int 和數(shù)組。必須先用 EasyMock.eq() 包裝它們,這樣才能在預(yù)期中捕捉它們的值。

清單 8 使用 EasyMock.expectLastCall() 調(diào)整預(yù)期的方法調(diào)用次數(shù)。在默認(rèn)情況下,預(yù)期的方法調(diào)用次數(shù)是一次。但是,我通過(guò)調(diào)用 .times(0, 1) setDocumentLocator() 設(shè)置為可選的。這指定調(diào)用此方法的次數(shù)必須是零次或一次。當(dāng)然,可以根據(jù)需要把預(yù)期的方法調(diào)用次數(shù)設(shè)置為任何范圍,比如 1-10 次、3-30 次。對(duì)于 characters() ,我實(shí)際上不知道將調(diào)用它多少次,但是知道必須至少調(diào)用一次,所以對(duì)它使用 .atLeastOnce() 。如果這是非 void 方法,就可以對(duì)預(yù)期直接應(yīng)用 times(0, 1) atLeastOnce() 。但是,因?yàn)檫@些方法返回 void ,所以必須通過(guò) EasyMock.expectLastCall() 設(shè)置它們。

最后注意,這里對(duì) characters() 的參數(shù)使用了 EasyMock.anyObject() EasyMock.anyInt() 。這考慮到了解析器向 ContentHandler 傳遞文本的各種方式。

?


?

mock 和真實(shí)性

有必要使用 EasyMock 嗎?其實(shí),手工編寫的 mock 類也能夠?qū)崿F(xiàn) EasyMock 的功能,但是手工編寫的類只能適用于某些項(xiàng)目。例如,對(duì)于 清單 3 ,手工編寫一個(gè)使用匿名內(nèi)部類的 mock 也很容易,代碼很緊湊,對(duì)于不熟悉 EasyMock 的開(kāi)發(fā)人員可讀性可能更好。但是,它是一個(gè)專門為本文構(gòu)造的簡(jiǎn)單示例。在為 org.w3c.dom.Node (25 個(gè)方法)或 java.sql.ResultSet (139 個(gè)方法而且還在增加)這樣的大型接口創(chuàng)建 mock 時(shí),EasyMock 能夠大大節(jié)省時(shí)間,以最低的成本創(chuàng)建更短更可讀的代碼。

最后,提出一條警告:使用 mock 對(duì)象可能做得太過(guò)分??赡馨烟嗟臇|西替換為 mock,導(dǎo)致即使在代碼質(zhì)量很差的情況下,測(cè)試仍然總是能夠通過(guò)。替換為 mock 的東西越多,接受測(cè)試的東西就越少。依賴庫(kù)以及方法與其調(diào)用的方法之間的交互中可能存在許多 bug。把依賴項(xiàng)替換為 mock 會(huì)隱藏許多實(shí)際上可能發(fā)現(xiàn)的 bug。在任何情況下,mock 都不應(yīng)該是您的第一選擇。如果能夠使用真實(shí)的依賴項(xiàng),就應(yīng)該這么做。mock 是真實(shí)類的粗糙的替代品。但是,如果由于某種原因無(wú)法用真實(shí)的類可靠且自動(dòng)地進(jìn)行測(cè)試,那么用 mock 進(jìn)行測(cè)試肯定比根本不測(cè)試強(qiáng)。

使用 EasyMock 更輕松地進(jìn)行測(cè)試


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 欧美黑人巨大3dvideo | 国产精品99久久99久久久看片 | 亚洲欧美精品成人久久91 | 国产亚洲欧美另类久久久 | 亚洲中午字幕 | 日韩女人做爰大片 | 欧美一级片在线免费观看 | 日韩欧美国产一区二区三区 | 久久思| 日日碰天天久久 | 久久婷婷激情综合中文字幕 | 久久精品免观看国产成人 | 岛国三级视频 | 五月婷婷在线视频 | a级做人爱免费播放 | 色大18成网站www在线观看 | 国产欧美日韩高清专区手机版 | 狠狠亚洲 | 国产女主播在线视频 | 伊人色婷婷 | 成人做爰毛片免费视频 | 中文日产国产精品久久 | 久久伊人草 | 97精品视频共享总站 | 国产日韩欧美在线观看不卡 | 午夜影视在线观看 | 韩国日本一级毛片免费视频 | 簧片在线播放 | 国产精品成人久久久 | 玖玖精品在线观看 | 久久久久久久蜜桃 | 一级毛片在线看在线播放 | 亚洲视频在线网 | 最猛黑人xxxⅹ黑人猛交 | 国产高清不卡一区二区 | 哪里有毛片 | 青娱乐91在线| 亚洲精品久久久中文字 | 无毒不卡 | 免费不卡毛片 | 精品久久久久久久一区二区伦理 |