2012-01-16 75 views
3

我有一些遺留的東西,並希望通過測試來覆蓋它。 有以下方法,我不知道如何使用mock進行測試。我使用正確的方式嗎?

public String listTransactions(Request request, Response response) { 
    String transactionFamily = request.get("transactionFamily"); 
    List transactions = service.fetchTransactions(transactionFamily); 
    responseBuilder.addElement("collection", transactions); 
    responseBuilder.addElement("token", tokenGenerator.next()); 
    String formattedResponse = responseBuilder.build(); 
    response.send(formattedResponse); 
    return null; 
} 

我的第一種方法是:

public void testResponseIsBuilt() { 
    request = stub(Request.class); 
    request.method("get").with("transactionFamily").willReturn("dummyFamily"); 
    response = mock(Response.class); 
    response.mehod("send").called(once()); 
    service = stub(TransactionService.class); 
    service.method("fetchTransactions").willReturn(testTransactions); 
    responseBuilder = mock(ResponseBuilder.class); 
    responseBuilder.method("addElement").called(once()).with("collection", testTransactions); 
    responseBuilder.method("addElement").called(once()).with("token", sampleToken); 
    responseBuilder.method("build").called(once());  
    responder.setService(service); 
    responder.setResponseBuilder(responseBuilder); 

    responder.listTransactions(request, response); 
} 

我知道一個測試用例應該覆蓋SUT的唯一一個方面。因此,考慮到這一點我能想象下面的一組測試:

  • testTransactionsFetchedForFamily
  • testTransactionsAddedToResponse
  • testTokenSetInResponse
  • testFormattedResponseBuilt
  • testResponseSent

例如執行 「testResponseBuilt」 我需要做這樣的設置(如上述)

  • 存根請求
  • 存根服務
  • 模擬responseBuilder 3個預計(2 addElement方法和1生成)

那裏不是太多嗎?這樣的設置是不是太複雜了?我在這裏「overmock」嗎?

我能想到把所有的東西responseBuilder成單獨的合作者,但它讓我有點瘋狂,因爲我剛剛提取ResponseBuilder本身。

我懷疑我在這裏寫單元測試錯過一些重要的點。

回答

2

你會有點用這些測試太遠。看來你的方法的責任是正確的設置,並將響應(從代碼判斷 - 命名可能會更好,如在什麼交易上市現在呢?)。這就是應該在這裏測試的。

編輯:

在第二次看,似乎大部分工作是由responseBuilder做 - 剩下的代碼只是對其進行設置。所以你真正可以在這裏測試的是它是否提供了預期的數據(這是一個或兩個測試)以及最終是否發送響應(第二/第三測試)。請注意,檢查.build是否被調用並不是必要的,因爲它的缺席將無法響應發送測試。

這意味着你需要在responseBuilder.add法)和response.send)嘲笑和驗證預期。測試響應格式屬於responseBuilder測試,就像測試交易是否被正確提取屬於service測試一樣。

(您也可能會驗證service調用與正確的參數,因爲它是硬編碼的,但如果你想成爲超級謹慎,這是唯一的)

總的來說,我會重拳出擊試驗#1和# 4並專注於其餘的。

而且爲了驗證這些期望,你必須去掉剩餘的依賴關係。沒有真正的解決方法。爲了測試單行代碼(以及它是否值得),您需要在決定您願意編寫多少代碼之間找到最佳位置。

+0

但是爲了設置一些模擬期望,我需要在測試中揭示一些內部結構,對吧?爲了獲得正確的響應格式,我需要準備responseBuilder以提供事務和令牌,所以我需要再次揭示內部消息。還是我完全失去了這裏? – grafthez 2012-01-16 20:55:10

+0

@grafthez:檢查我的編輯 - 你是正確的,你想測試的是responseBuilder是否餵給正確的數據和是否發送響應。其他測試屬於不同的類別。 – 2012-01-16 21:09:39

1

測試套件應包含請求,服務應提及的設置方法。這將確保您爲所有測試用例重用變量。越是模塊化,你就可以獲得更細緻的反應。希望這可以幫助你。

+0

當然你是對的。我已經在這裏清楚了 - 它會在實際實現中轉到setUp()。我的問題有點不同:我的實現做了「a b c d」並測試「b」期望需要設置「a」。爲了測試「c」期望值,我需要設置「ab」,依此類推...... – grafthez 2012-01-16 20:58:01

+0

JUnit將測試一個流,所以據我所知你需要爲完整的測試用例測試d並給出c,b的斷言和a。你的測試套件應該只包含一個測試流程的測試。 – Abhi 2012-01-16 21:04:18