web-dev-qa-db-ja.com

同じオブジェクトでMockito.whenを複数回呼び出しますか?

MockitoをSpringで使用しようとするとき、Bean宣言を介してMockオブジェクトを作成して...

<bean id="accountMapper" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="org.example.persistence.mybatis.mappers.AccountMapper" /> 
</bean>     

... Mockito.whenをMockオブジェクトをリセットせずに複数回呼び出すと、奇妙な動作が見つかりました。次に例を示します。

Mockito.when(this.accountMapper.createBadGrammarException()).thenThrow(new BadSqlGrammarException("Bla", null, new SQLException()));

このコード( "Mockito.when")がテスト中に(同じモックで)複数回呼び出されるとすぐに、エラー(BadSqlGrammerExceptionは、この例外が実際に予期されていたものであっても)で失敗します-失敗します例外をスローせず、手動でスローすると正常に機能する場合)。これは予想される動作ですか? Mockito は毎回新しいモックを作成することを提案しているようです。つまり、各メソッドにDAOを作成することを意味します...?

Mockito.whenメソッドを2回呼び出すと、正確にはどうなりますか?モックはどのように反応する必要がありますか?動作を置き換えますか?それを無視します?残念ながら、ほとんどの検索では、メソッド自体への複数の呼び出しに対して異なる結果を返す方法の結果しか得られませんが、Mockito.whenへの複数の呼び出しで予期される結果は得られません。

ここでは単にMockitoとベストプラクティスを理解しようとしているだけです。SEEMSが機能するという理由だけで何かを進めるのは悪い考えのようです...

8
Florian Schaetz

Mockito.whenの問題の1つは、それに渡す引数が、スタブしようとしている式であることです。したがって、同じメソッド呼び出しでMockito.whenを2回使用すると、2回目に使用すると、最初にスタブした動作が実際に得られます。

実際には、Mockito.whenを使用しないことをお勧めします。それを使用するときに陥る可能性のある多くのトラップがあります-代わりに他の構文が必要なかなりのケース。 「より安全な」代替構文は、Mockitoメソッドの「do」ファミリーです。

doReturn(value).when(mock).method(arguments ...);
doThrow(exception).when(mock).method(arguments ...);
doAnswer(answer).when(mock).method(arguments ...);

だからあなたの場合、あなたは欲しい

doThrow(new BadSqlGrammarException(??, ??, ??)).when(accountMapper).createBadGrammarException();

Mockitoを使い始める場合は、「do」ファミリーの使い方を学ぶことをお勧めします。これらはvoidメソッドをモックする唯一の方法であり、Mockitoのドキュメントでは特にそれについて言及しています。ただし、Mockito.whenを使用できるときはいつでも使用できます。したがって、「do」ファミリを使用すると、テストの一貫性が向上し、学習曲線が短くなります。

must "do"ファミリーを使用する場合の詳細については、 Forming Mockito "grammars" の私の回答を参照してください。

22

簡単な答えは:
Mockito.when(object.fooMethod()).then()と記述すると、実際にfooMethod()が呼び出されます。
もう1つの点は、モックされたオブジェクトを呼び出したため、初めてそれを観察できないことです。しかし、2回目にwhenを記述するときは、fooMethod()に対していくつかの動作があります(以前に設定した場合は、例外です)。

これをよりよく確認するには、spyオブジェクトを使用します。

_Bar spyBar = Mockito.spy(Bar.class)
when(spyBar.fooMethod()).then()...
_

およびfooMethod()が実際に呼び出されます。

2
Vova Yatsyk