3

WidgetProcessor別のクラスに依存するクラスがありますFizzChecker:

public class FizzChecker {
    public boolean hasMoreBuzz() {
        // Sometimes returns true, sometimes returns false.
    }
}

このメソッドは、次のようhasMoreBuzz()に内部から呼び出されます。WidgetProcessor

public class WidgetProcessor {
    public int process() {
        while(fizzChecker.hasMoreBuzz()) {
            // ... process stuff in here
        }
    }
}

次の場合のテストケースを書きたい:

  • fizzChecker.hasMoreBuzz()最初に呼び出されたときに false を返します (したがって、ループは実行されません)。
  • fizzChecker.hasMoreBuzz()5 回目の呼び出しで false を返す

Mockitoでこれを達成する方法を見つけようとしています。これまでのところ、私の最高の(ひどい)試み:

WidgetProcessor fixture = new WidgetProcessor();
FizzChecker mockFizzChecker = Mockito.mock(FizzChecker.class);

// This works great for the first test case, but what about the 2nd
// where I need it to return: true, true, true, true, false?
Mockito.when(mockFizzChecker).hasMoreBuzz().thenReturn(false);

fixture.setFizzChecker(mockFizzCheck);

fixture.process();

// Assert omitted for brevity

前もって感謝します。

4

2 に答える 2

7

複数の値を に渡しthenReturnたり、チェーンを維持したりできます。スタブ化されたメソッドを連続して呼び出すと、アクションが順番に返され、すべての呼び出しに対して最後のアクションが繰り返されます。例:

// will return true four times, and then false for all calls afterwards
when(mockFizzChecker.hasMoreBuzz()).thenReturn(true, true, true, true, false);
when(mockFizzChecker.hasMoreBuzz())
    .thenReturn(true)
    .thenReturn(true)
    .thenReturn(true)
    .thenReturn(true)
    .thenReturn(false);
// you can also switch actions like this:
when(someOtherMock.someMethodCall())
    .thenReturn(1, 2)
    .thenThrow(new RuntimeException());

おそらく、それらを個別に設定する必要があります。

public class WidgetProcessorTest {
  private WidgetProcessor processor;
  private FizzChecker mockFizzChecker;

  @Before public void setUp() {
    processor = new WidgetProcessor();
    mockFizzChecker = Mockito.mock(FizzChecker.class);
    processor.setFizzChecker(mockFizzChecker);
  }

  @Test public void neverHasBuzz() {
    when(mockFizzChecker.hasMoreBuzz()).thenReturn(false);
    processor.process();
    // asserts
  }

  @Test public void hasFiveBuzzes() {
    when(mockFizzChecker.hasMoreBuzz())
        .thenReturn(true, true, true, true, false);
    processor.process();
    // asserts
  }
}

hasMoreBuzz最後の注意: 実際には、複数の呼び出し (および など)を調整する必要がある場合がありますgetNextBuzz。複雑になり始め、多くのテストでこれを記述することが予測される場合は、Mockito をスキップして、代わりFakeFizzChecker.

于 2013-02-18T02:24:29.657 に答える
0

Answersを使用してみてください。これにより、hasMoreBuzz()メソッドが呼び出されたときにコードを実行できるようになります。

上記のリンクの例を見てください。Answerオブジェクトを作成し、answer()メソッドを実装してカウンターを保持する場合、そのカウンターの値に基づいてアクションを実行できます。

編集:これを確認するためのクイックテストプログラムを作成しました。ここにあります:

package com.ejk;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;

public class SO {
    @Test
    public void testIt() {          
        IFoo mock = mock(IFoo.class);
        MyAnswer myAnswer = new MyAnswer();
        when(mock.doFoo()).then(myAnswer);
        for (int i=1; i<10; i++) {
            System.out.println(i+ ") " + mock.doFoo());
        }
    }
    class MyAnswer implements Answer<Boolean> {
        int counter = 1;
        @Override
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            return (counter++ == 5) ? Boolean.FALSE : Boolean.TRUE;
        }

    }
    interface IFoo {
        boolean doFoo();
    }
}
于 2013-02-18T00:27:25.567 に答える