2012-01-16 4 views
3

私はいくつかの遺産を持っており、それをテストでカバーしたいと思っています。 モックを使ってテストする方法がわからない次の方法があります。私はモックを正しい方法で使用していますか?

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" 私は(上記のように)このように設定を行う必要がありスタブサービス

  • 3つのを期待(2 addElementのと1つのビルド)
  • とモックresponseBuilder

    • スタブ要求
    • を実行しますそこにあまりにもないですか?そのような設定は複雑すぎるのではないですか?私はここで "オーバーモック"していますか?

      私は、すべてのresponseBuilderのことを別の協力者にすることができますが、ResponseBuilder自体を抽出したのでちょっと狂っています。

      ユニットテストを書く際に重要な点がいくつかあると思いますが、

    答えて

    2

    あなたはこれらのテストで少し遠すぎます。あなたのメソッドの責任は正しく設定し、応答を送信することです(コードネーミングから判断するとより良いかもしれません。トランザクションになります)今ですか?それがここでテストされるべきものです。

    編集:二表情で

    、仕事の大半はresponseBuilderによって行われているようです - 残りのコードはそれを設定します。実際にここでテストできるのは、期待されるデータ(1つか2つのテスト)と最後にレスポンスが送られるかどうか(第2 /第3テスト)です。 .buildが呼び出されているかどうかを確認することは、その不在が応答送信テストに失敗するため、必要ではないことに注意してください。

    これは、あなたが(.sendresponseBuilder.add法)とresponseに期待を模擬して確認する必要がありますを意味します。テスト応答形式はresponseBuilderテストに属し、トランザクションが正しくフェッチされているかどうかをテストするのと同様に、serviceテストに属します。

    (あなたはまた、おそらくそれは、ハードコードだとしてserviceが正しいパラメータで呼び出されていることを確認できたが、それはあなたが超慎重になりたい場合にのみです)

    全体的に、私はテスト#1と#を打ちます残りのものに焦点を合わせる。

    これらの期待を検証するためには、残りの依存関係を除外する必要があります。その周りには本当の方法はありません。コードの単一行をテストするために書くべきコードの量と、その価値があるかどうかを判断する間に、甘い味を見つける必要があります。

    +0

    しかし、いくつかの模擬期待を設定するには、私のテストでいくつかの内部構造を明らかにする必要がありますよね?そして、正しい応答形式を得るためには、私はresponseBuilderにトランザクションとトークンを提供する準備をする必要があるので、内部を再び明らかにする必要があります。あるいは、私はここで完全に失われていますか? – grafthez

    +0

    @grafthez:私の編集を確認してください - あなたは正直なところです。あなたがテストしたいのは、responseBuilderに正しいデータが与えられているかどうか、そして応答が送られているかどうかです。他のテストは異なるクラスに属します。 –

    1

    テストスイートには、request、serviceを記述するsetupメソッドが含まれている必要があります。これにより、すべてのテストケースで変数を再利用できるようになります。よりモジュラ的であれば、より細かい応答を得ることができます。これがあなたを助けることを願っています

    +0

    確かにあなたは正しいです。私はここでそれを明確にしました。実際の実装ではsetUp()に行きます。私の問題は少し異なります:私の実装は "a b c d"を行い、 "b"の期待には "a"を設定する必要性をテストします。 「c」の期待値をテストするには、「ab」などの設定が必要です。 – grafthez

    +0

    JUnitはフローをテストするため、完全なテストケースでdをテストし、c、bおよびa。テストスイートには、フローをテストするテストが1つだけ含まれている必要があります。 – Abhi