3

テストしたい次のオブジェクトがあります。

   public class MyObject {

    @Inject
    Downloader downloader;

    public List<String> readFiles(String[] fileNames) {
        List<String> files = new LinkedList<>();
        for (String fileName : fileNames) {
            try {
                files.add(downloader.download(fileName));
            } catch (IOException e) {
                files.add("NA");
            }
        }
        return files;
    }
}

これは私のテストです:

@UseModules(mockTest.MyTestModule.class)
@RunWith(JukitoRunner.class)
public class mockTest {

    @Inject Downloader downloader;
    @Inject MyObject myObject;

    private final String[] FILE_NAMES = new String[] {"fail", "fail", "testFile"};
    private final List<String> EXPECTED_FILES = Arrays.asList("NA", "NA", "mockContent");

    @Test
    public void testException() throws IOException {
        when(downloader.download(anyString()))
                .thenThrow(new IOException());

        when(downloader.download("testFile"))
                .thenReturn("mockContent");

        assertThat(myObject.readFiles(FILE_NAMES))
                .isEqualTo(EXPECTED_FILES);
    }

    public static final class MyTestModule extends TestModule {
        @Override
        protected void configureTest() {
            bindMock(Downloader.class).in(TestSingleton.class);
        }
    }
}

anyString()特定の引数のマッチャーを上書きしています。メソッドをスタブ化しdownload()て、特定の引数の値を返すようにし、それ以外の場合は によって処理される IOException をスローしMyObject.readFilesます。

ここで奇妙なのは、2 番目のスタブ ( downloader.download("testFile")) が最初のスタブ ( ) で設定された IOException をスローすることdownloader.download(anyString())です。最初のスタブで別の例外をスローすることで、それを検証しました。

追加のスタブを追加するときに例外がスローされる理由を誰かが説明できますか? スタブを作成してもメソッド/他のスタブは呼び出されないと思いました。

4

3 に答える 3

2

問題は、あなたが書くときです

when(downloader.download("testFile")).thenReturn("mockContent");

最初に呼び出されるのはdownloader.download、例外をスローするために既にスタブ化されている です。

解決策は、Mockito が提供するもう少し用途の広いスタブ構文を使用することです。この構文には、スタブ時に実際のメソッドを呼び出さないという利点があります。

doThrow(IOException.class).when(downloader).download(anyString());
doReturn("mock content").when(downloader).download("test file");

この2番目の構文の他の利点をリストしました。ここでの回答です

于 2016-09-07T00:55:04.263 に答える
1

スタブを作成してもメソッド/他のスタブは呼び出されないと思いました。

スタブはモック メソッドを呼び出しているため、この仮定は間違っています。テスト メソッドはプレーン Java のままです。

のスタブは特定の文字列のスタブを上書きするためanyString、2 つのテストを記述するか、2 つの特定の引数に対してスタブを作成する必要があります。

when(downloader.download("fail")).thenThrow(new IOException());

when(downloader.download("testFile")).thenReturn("mockContent");

Mockito は非常に洗練されたコードであり、次のように書けるように最善を尽くします。

when(downloader.download(anyString())).thenThrow(new IOException());

これは、「<code> downloaders モックdownloadメソッドがanyString引数thenThrowanで呼び出されたとき」を意味しますIOException(つまり、左から右に読み取ることができます)。

ただし、コードはプレーン Java であるため、呼び出しシーケンスは実際には次のようになります。

String s1 = anyString(); // 1
String s2 = downloader.download(s1); // 2
when(s2).thenThrow(new IOException()); // 3

舞台裏で、Mockito はこれを行う必要があります。

  1. ArgumentMatcher任意の文字列引数の を登録します
  2. 引数が以前に登録されたによって定義されているモックにメソッド呼び出しdownloadを登録しますdownloaderArgumentMatcher
  3. 以前に登録したメソッド呼び出しのアクションをモックに登録する

今電話したら

 ... downloader.download("testFile") ...

downloaderモックはアクション レジスタがあるかどうかをチェックし("testFile"任意の文字列のアクションが既に存在するため、存在します)、それに応じてIOException.

于 2016-09-06T05:05:54.293 に答える
1

2 番目のモック ステートメントは、最初のモック ステートメントによってオーバーライドされます (両方のモック ステートメントが文字列引数を渡しているため)。try をカバーするだけでなく、モック テストをキャッチバックする場合は、2 つの異なるテスト ケースを記述します。

于 2016-09-05T22:53:24.240 に答える