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するときは戻り値を評価しろ!