mock 是指當用來被 unit 測試對象的物件,需要相依某些其他物件才能正常運作時,
以一個"假冒"的 mock 物件實作被相依的物件之界面,設定給 unit 測試對象物件,
目的是隔離unit 測試對象物件與部署環境,並於測試後直接檢查mock物件的變化,
達到不需要部署測試對象物件到環境,也可以了解測試對象物件對環境的影響是否符合要求。
easymock api 方便我們建立 mock 物件,官方範例如下:
http://www.easymock.org/EasyMock2_5_2_Documentation.html
以一個被測試的 ClassUnderTest 物件,使用到一個 Collaborator 介面為例,
將要為 Collaborator 建立 mock ,並給 ClassUnderTest 做測試。
public class ClassUnderTest { // ...
public void addListener(Collaborator listener){
// ...
}
public void addDocument(String title, byte[] document) {
// ...
}
public boolean removeDocument(String title) {
// ...
}
public boolean removeDocuments(String[] titles) {
// ...
}
}
public interface Collaborator { void documentAdded(String title);
void documentChanged(String title);
void documentRemoved(String title);
byte voteForRemoval(String title);
byte[] voteForRemovals(String[] title);
}
測試的 TestCase 實作如下:
import static org.easymock.EasyMock.*; import junit.framework.TestCase;
public class ExampleTest extends TestCase {
private ClassUnderTest classUnderTest;
private Collaborator mock;
protected void setUp() {
mock = createMock(Collaborator.class); // 1 建立 mock
classUnderTest = new ClassUnderTest();
classUnderTest.addListener(mock);
}
public void testAddDocument() {
mock.documentAdded("New Document"); // 2 設定 mock 物件將replay後該有的行為
replay(mock); // 3 切換 mock 為 replay 準備狀態
classUnderTest.addDocument("New Document", new byte[0]);
}
}
重點在 replay() 之前 mock 物件運作的行為不是 Collaborator 真正的行為,而是,
"預先告知" replay() 之後, mock 應該要有什麼 method 被呼叫,傳進來的參數是什麼…等。
而 replay() 之後, classUnderTest.addDocument("New Document", new byte[0]);
如果沒有觸發 mock 物件"預先告知"的行為,就會產生錯誤使得測試失敗。