假設我們要測試資料庫,除了連接真正的資料庫或是本地端的測試資料庫以外,我們也可以生成假的物件來測試,以下列出 Stub / Mock 這兩種做法的測試案例,大家可以自行體會其中的差別。
Stub
/** 能連接至 MySQL 的實作 */
public class DatabaseMySql implements Database
{
public boolean connect()
{
// 省略
return true; // 連接真正的的資料庫,真的連上才回傳 true。
}
}
/** 為了測試用的實作 */
public class DatabaseStub implements Database
{
public boolean connect()
{
return true; // 直接回傳 true。
}
}
// 分隔線
public void testStub()
{
Database databaseStub = new DatabaseStub(); // 建立 stub
System.out.println(databaseStub.connect()); // 印出 true
}
Mock
public void testMock()
{
Database databaseMock = mock(Database.class); // 使用 mockito 建立 mock
when(databaseMock.connect()).thenReturn(true); // 當呼叫 connect() 就回傳 true
System.out.println(databaseStub.connect()); // 印出 true
}
Stub vs Mock
對我來說如果用 Mock 寫法的話:
- 要替每個測試定義其 databaseMock 物件的輸入輸出。
- 無需定義 Database 介面。
- 無需實作 DatabaseStub 類別,複寫所有 Database 介面定義的方法。
我實務上比較常用 Stub 的做法:
- 因為不用特別引入第三方函式庫就可以實現了。
- 而且對介面開發而非對實作開發也本來就是一個好的習慣。
關於更專業的解釋,可以參考 Mocks Aren't Stubs 這一篇經典文章。
0 則回應: