2017-02-26 10 views
0

私はMockitoを初めて使っています。 getAllFoo()メソッドのすべてのブランチをテストするために、私のテストクラスにMockitoのAnswerインターフェイスを使用しようとしています。私はisFooComplete()falseに戻して最初の2回呼び出すと、actualFooにのオブジェクトが含まれているので、テストの最後にtrueを返します。メソッドのすべてのブランチをテストするためのMockitoの回答インタフェースの実装

問題は、私はservicegetAllFoo()を呼んでいるループのために、falseが最初に返された内側(あなたがgetAllFoo()メソッドの実装を見て予想通り)、そして、テストは無限ループに陥ってしまうということです。

getAllFoo()falseを2回返すようにこのテストを変更してから、trueを返してループを終了するにはどうすればよいですか?

サービスクラス:

public class ServiceImpl { 

    @Autowired 
    FooService fooService; 

    public Collection<Foo> getAllFoo() { 
     Collection<Foo> allFoo = new ArrayList<>(); 
     boolean complete = fooService.isFooComplete(); 
     boolean available = fooService.isFooAvailable(); 
     while (!complete && available) { 
      Foo foo = fooService.getAvailableFoo(); 
      allFoo.add(foo); 
     } 
     return allFoo; 
    } 
} 

Testクラス:

public class ServiceImplTest { 

    @InjectMocks 
    ServiceImpl service = new ServiceImpl(); 

    @Mock 
    FooService fooService; 

    class MyAnswer implements Answer<Boolean> { 
     int counter = 0; 

     @Override 
     public Boolean answer(InvocationOnMock inovation) 
      throws Throwable { 
      return (counter++ > 2) ? Boolean.TRUE : Boolean.FALSE; 
     } 
    } 

    @Test 
    public void testGetAllFoo() { 
     MyAnswer myAnswer = new MyAnswer(); 

     MockFoo mockFoo = new MockFoo(); 

     when(fooService.isFooComplete()).thenAnswer(myAnswer); 
     //when(fooService.isFooComplete()).thenReturn(false, false, true); 
     when(fooService.isFooAvailable()).thenReturn(true); 
     when(fooService.getAvailableFoo()).thenReturn(mockFoo); 

     Collection<Foo> actualFoo = new ArrayList<>(); 
     for (int i = 0; i < 3; i++) { 
      actualFoo = service.getAllFoo(); 
     }    
     assertTrue(actualFoo.contains(mockFoo)); 
     assertEquals(2, actualFoo.size()); 
    } 
} 

答えて

1

あなたの例では、あなたのカウンタをインクリメントしていません。カウンタは常に0なので、返信してcounter >= 2に変更する前にcounter++を実行する必要があります。

しかし、このアンサーでFooServiceロジックの一部を実装しているようです。私はwhen(fooService.isFooComplete()).thenReturn(true, true, false)がここでより良い選択かもしれないと思います。

+0

大漁:

おそらくあなたはこれをやりたいです。私はそれを増やすように編集しました。 最初に私のコードで間違ってコピーしました: 'service.getAllFoo()'はループ内にあったはずです(これも編集しました)。これが問題を作り出しています:最初の呼び出しはfalseを返し、無限ループでカウンタがインクリメントして最終的に真を返すことができます。 Answerの代わりに 'thenReturn(false、false、true)'を使ってあなたの提案を試みましたが、それでも問題は解決しません。他のアイデア? –

0

無限ループがあります。 while (!complete && available)は、完了ブロックと使用可能ブロックがwhileブロック内で変更されないため、終了しません。カウンターの上に

Collection<Foo> allFoo = new ArrayList<>(); 
boolean complete = fooService.isFooComplete(); 
boolean available = fooService.isFooAvailable(); 
while (!complete && available) { 
    Foo foo = fooService.getAvailableFoo(); 
    allFoo.add(foo); 
    complete = fooService.isFooComplete(); 
    available = fooService.isFooAvailable(); 
} 
+0

そうかもしれませんが、実際には '!complete'は常に最終的にfalseと評価され、ループから抜け出します。問題は、 'fooService.isFooComplete()'がユニットテストでその動作を模倣するようになっていることです。 –

+0

私はそうは思わない。最初のテストでcompleteをfalseに設定してtrueにすると、whileループはこれまでに終了しません! **!completeは常に最終的にfalse **と評価されますが、これは正しくありません。 'isFooComplete'がfalseを返し、' ifFooAvailable'がtrueを返した場合、whileループは入力され、決して放置されません。なぜなら、両方の変数がループ内で値を変更してループが永遠に続くことはないからです。 –

関連する問題