軟體測試:我不在新創公司用mocks

為了確保軟體品質,多少會寫點測試。

常會看到文章提倡使用mocking的手法,說是要獨立測試程式的各個部份比較好。

我觀察這個手法很久了,遲遲不願意真正應用。

我總覺得mocking讓測試的code變得很冗長、不好讀。

最近終於發現,其實不少人跟我抱持同樣看法。

這邊舉Testing on the Toilet: Don’t Overuse Mocks一文中提到的例子。

不使用mocks、寫出有相依性的test長這樣:

public void testCreditCardIsCharged() {
  paymentProcessor = new PaymentProcessor(creditCardServer);
  paymentProcessor.processPayment(creditCard, Money.dollars(500));
  assertEquals(500, creditCardServer.getMostRecentCharge(creditCard));
}

使用mocking達到測試環境獨立的test長這樣:

public void testCreditCardIsCharged() {
  paymentProcessor = new PaymentProcessor(mockCreditCardServer);
  when(mockCreditCardServer.isServerAvailable()).thenReturn(true);
  when(mockCreditCardServer.beginTransaction()).thenReturn(mockTransactionManager);
  when(mockTransactionManager.getTransaction()).thenReturn(transaction);
  when(mockCreditCardServer.pay(transaction, creditCard, 500)).thenReturn(mockPayment);
  when(mockPayment.isOverMaxBalance()).thenReturn(false);
  paymentProcessor.processPayment(creditCard, Money.dollars(500));
  verify(mockCreditCardServer).pay(transaction, creditCard, 500);
}

不但可讀性下降、還得多花時間撰寫mocks。

在新創公司,我不寫mocks的原因有兩個:

一、新創公司,軟體越快上線越好。花時間寫mocks,太不划算了。
二、既然軟體架構不大,反正任何一個測試fail,整個application都會壞掉。tests無論如何都得全部pass才行。

想來想去,只有在用到第三方library或API、不方便在tests中真正呼叫時,才會想用mocks。

話雖如此,有看法認為應該用interface再加上一層薄layer來解決test第三方library的問題:

Test Smell: Everything is mocked

如果是在開發framework就另當別論了。要確實分別測試各個部份才行。

Laravel的tests

話雖如此,也許更資深、接觸的軟體架構更大之後,我會改變想法也說不定。