Mock 與 Stub 的差別

假設我們要測試資料庫,除了連接真正的資料庫或是本地端的測試資料庫以外,我們也可以生成假的物件來測試,以下列出 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 則回應: