spock + mockitoでverifyするときの注意点
mockitoでverifyするときにテストが通らなくてハマったのでメモ
サンプルコード
プロダクト
public class Sample { public interface Repository { int insert(String data); } @AllArgsConstructor public static class Main { private final Repository repository; public void run() { repository.insert("hello world"); } } }
Repository#insert()は何かデータを挿入して、結果としてIDを返却するようなメソッドです
そのメソッドをMain#run()で呼び出しています
テスト
Main#run()の中でRepository#insert()を正しく呼び出せているかをテストします
class SampleTest extends Specification { def "test"() { setup: def mockRepository = Mockito.mock(Sample.Repository) def sut = new Sample.Main(mockRepository) when: sut.run() then: Mockito.verify(mockRepository, Mockito.times(1)).insert(Mockito.any(String)) } }
これで実行したらうまく通りそうですが、実行するとこうなります
SampleTest > test FAILED
Condition not satisfied:
Mockito.verify(mockRepository, Mockito.times(1)).insert(Mockito.any(String))
| | | | |
| | | 0 null
| | Wanted invocations count: 1
| Mock for Repository, hashCode: 2069833259
Mock for Repository, hashCode: 2069833259
at util.SampleTest.test(SampleTest.groovy:18)
なんでや!
テストが通らない理由
テストが通らない理由はテストのthenのところ
then: Mockito.verify(mockRepository, Mockito.times(1)).insert(Mockito.any(String))
ここでinsertが0を返します
thenの中では各行が評価されますが、行の結果が0の場合はテスト失敗とみなされます
だから通らない
結論: 戻り値のあるメソッドをverifyするときは戻り値を評価しろ
thenをこう書くべきです
then: Mockito.verify(mockRepository, Mockito.times(1)).insert(Mockito.any(String)) == 0
まとめ
spockのテストでMockito.verify()が通らなくてハマりました
原因は戻り値を評価していないこと
なので戻り値のあるメソッドをverifyするときは戻り値を評価しろ!