Mockk逆引きチートシート

# はじめに
なんやかんやで便利な[Mockk](https://mockk.io/)だけど割と情報が少ないので逆引きチートシートを自分用に用意

随時更新したいなぁ〜...

*更新履歴*
2019年9月20日 「特定の型が引数にセットされてメソッドが呼ばれたかを確認したい」を追加
2020年7月13日　「KotlinのCompanionなメソッドをMock化したい」を追加

# あるメソッドをMock化したい

```kotlin
class SomeClass {
  fun add(a:Int, b:Int) = a + b
}
fun someTest() {
  val someClass = mockk<SomeClass>()
  every { someClass.add(any(), any()) } returns 12
}
```

実装ポイント

 * everyのカッコ内が対象のメソッドを書き、returnsで結果を定義
 * 引数がある場合は指定できる。なんでもいい場合はany()、型を指定したい場合は`any<Int>()`的な感じ


# テスト対象内にあるプライベートメソッドをMock化したい
```kotlin
class SomeTargetClass {
  private fun minus(a:Int, b:Int) = a - b
}

@Test
fun someTest() {
  val someTargetClass = spyk<SomeTargetClass>(recordPrivateCalls = true)
  every { someTargetClass["minus"](any(), any()) } returns 12
}
```

実装ポイント

 * テスト対象のクラスをspyk化する。これでテスト対象のクラスを操作できる
 * spyk化する際に`recordPrivateCalls = true`を指定することでprivateメソッドにアクセスできるようになる
 * プライベートメソッドにアクセスするときは`インスタンス["メソッド名"](引数)`的な感じで書く


# とりあえずMock化したクラスのメソッドはなんでもでいいからオブジェクト返して欲しい
メソッドが呼ばれてるかどうかを確認したい時に使える
コンストラクタ引数で指定されたパラメータのMock化が面倒な時に便利

```kotlin
class SomeClass {
  fun add(a:Int, b:Int) = a + b
}

class SomeTargetClass constructor(private val someClass:SomeClass) {
  fun minus(a:Int, b:Int) = someClass.add(a, -b)
}

@Test
fun someTest() {
  val someClass = mockk<SomeClass>(relaxed = true)
  val someTargetClass = SomeTargetClass(someClass)
  someTargetClass.minus(1,2)
  verify(exactly = 1) { someClass.add(any(), any()) }
}
```

実装ポイント

 * mockk化する時に`relaxed = true`を指定する。これで指定したMockのレスポンスはデフォルト値を返すようになる

# あるMock化したメソッドのレスポンス時に処理を挟みたい

```kotlin
class SomeTargetClass {
  fun minus(a:Int, b:Int) = a - b
}

@Test
fun someTest() {
  val someTargetClass = spyk<SomeTargetClass>(recordPrivateCalls = true)
  every { someTargetClassminus(any(), any()) } answers {
   println("mogemoge")
   returns 12
  }
}
```

実装ポイント

 * everyに対して`returns`ではなく`answers`を使うことで処理を挟める

# あるMock化したメソッドのレスポンス時に処理を挟む時に引数をいじりたい
関数引数をとるようなケースで使えると思うぞ

```kotlin
class CallBack {
  val exec:(Int)->Unit
}

class SomeClass {
  fun add(a:Int, b:Int, callBack:CallBack) {
     val result = a + b
     callBack.exec(result)
   }
}

class SomeTargetClass constructor(private val someClass:SomeClass) {
  fun minus(a:Int, b:Int) { 
      someClass.add(a, -b, CallBack({
        printResult(it)
      })) 
    }

  fun printResult(result:Int) {
    println(result)
  }
}

@Test
fun someTest() {
  val someClass = mockk<SomeClass>()
  val someTargetClass = SomeTargetClass(someClass)
  every { someClass.add(any(), any(), any()) answers {
      thirdArg<CallBack>().exec(12)
  }
  someTargetClass.minus(1,2)
  verify(exactly = 1) { printResult(12) }
}
```

実装ポイント

 * `answers`の中では`thirdArg<型>()`で引数のデータにアクセスできる。`firstArg`なら第1引数,`secondArg`なら第2引数となっている。4つ目以降も同じ感じ

# JavaのstaticなクラスをMock化したい
`LocalDateTime.now()`のお供に

```kotlin
@Before
fun setup() {
  mockkStatic(LocalDateTime::class)
  every { LocalDateTime.now() } returns LocalDateTime.of(2020, 1, 1, 11, 11)
}
```

実装ポイント

 * `mockkStatic`を使う

# KotlinのCompanionなメソッドをMock化したい

```kotlin
class SomeCompanionObject {
  companion object create(): SomeCompanionObject = SomeCompanionObject()
}

@Before
fun setup() {
  val mock = mockk<SomeCompanionObject>()
  mockkObject(SomeCompanionObject)
  every { SomeCompanionObject.create() } returns mock
}
```

実装ポイント

* `mockkObject`を使う

# 変数のないメソッドをMock化したい
init時にInjectしてるような場合に便利かも

```kotlin
class SomeClass {
   injector(someTargetClass:SomeTargetClass)
}

class SomeTargetClass constructor(private val someClass:SomeClass) {
  init {
    someClass.injector(this)
  }
}

class SomeTargetClassTest {
  private val someClass = mockk<SomeClass>()
  @Before
  fun setup() {
    every { someClass.injector(any()) } just runs
  }
}
```

実装ポイント

 * `just runs`でUnitを返す関数を実行する感じ

# 特定の型が引数にセットされてメソッドが呼ばれたかを確認したい
ジェネリクスとかSealedクラス使って引数が複数の型を取りうる場合のテストに使えるぞ

```kotlin
class SomeTargetClass<T> {
  fun print(t:T) = println(t.toString())
}

@Test
fun someTest() {
  val someClass = SomeTargetClass<String>
  someClass.print("abc")
  verify { someClass.print(ofType<String>) }
}
```

実装ポイント

 * 引数に`ofType<型>`と指定することで、指定した型でメソッドが引数として呼ばれたかが判別できる