[Kotlin] MockKまとめ

# はじめに
MockKとは **Kotlin用のモックライブラリ** です。

この記事では[公式ドキュメント](https://mockk.io/)を日本語に訳し、自分用に使い方をまとめたものになります。これから辞書代わりに使っていこうと考えています。
私自身まだ実践で使ったことない機能もありますので、ニュアンス違うよなどの指摘やアドバイスを頂けると幸いです。


# インストレーション(Installation)
始めるために必要なことは、`MockK`ライブラリに依存関係を追加することです。

## Gradle / Mavenの依存関係(Gradle/maven dependency)
| アプローチ             | 命令 |
|:---------------------|:------------|
| Gradle               | `testImplementation "io.mockk:mockk:{version}"` |
| Gradle(Kotlin DSL)   | `testImplementation("io.mockk:mockk:{version}")` |
| Unit                 | `testImplementation "io.mockk:mockk:{version}"` |
| Instrumented         | `androidTestImplementation "io.mockk:mockk-android:{version}"` |
| Common multiplatform | `testImplementation "io.mockk:mockk-common:{version}"` |

`{version}`は以下のバージョンに対応します。

- Kotlin 1.3+およびCoroutines 1.0+バージョン
- Kotlin 1.2互換バージョン

# DSLの例(DSL examples)
最も単純な例です。デフォルトではモックは厳密なので、何らかの動作を提供する必要があります。

```kotlin
val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

verify { car.drive(Direction.NORTH) }

confirmVerified(car)
```
## アノテーション(Annotations)
アノテーションを使用して、モックオブジェクトの作成を簡素化できます。

```kotlin
class TrafficSystem {
  lateinit var car1: Car
  
  lateinit var car2: Car
  
  lateinit var car3: Car
}

class CarTest {
  @MockK
  lateinit var car1: Car

  @RelaxedMockK
  lateinit var car2: Car

  @MockK(relaxUnitFun = true)
  lateinit var car3: Car

  @SpyK
  var car4 = Car()
  
  @InjectMockKs
  var trafficSystem = TrafficSystem()
  
  @Before
  fun setUp() = MockKAnnotations.init(this, relaxUnitFun = true) // すべてのモックに対してrelaxUnitFunをオンにします

  @Test
  fun calculateAddsValues1() {
      // ... use car1, car2, car3 and car4
  }
}
```
インジェクションは、最初にプロパティを名前で照合し、次にクラスまたはスーパークラスで照合します。カスタマイズのために`lookupType`パラメータを確認してください。

`private`が適用されている場合でも、プロパティが注入されます。インジェクションのコンストラクターは、引数の最大数から最小数まで選択されます。

デフォルトでは、`@InjectMockKs`は、`lateinit var`または割り当てられていない`var`のみを挿入します。これを変更するには、`overrideValues = true`を使用します。これは、すでに何らかの方法で初期化されている場合でも値を割り当てます。`val`を注入するには、`injectImmutable = true`を使用します。短い表記の場合、デフォルトで`@InjectMockKs`と同じことを行う`@OverrideMockKs`を使用しますが、この2つのフラグをオンにします。

### JUnit5
JUnit5では、`MockKExtension`を使用してモックを初期化できます。

```kotlin
@ExtendWith(MockKExtension::class)
class CarTest {
  @MockK
  lateinit var car1: Car

  @RelaxedMockK
  lateinit var car2: Car

  @MockK(relaxUnitFun = true)
  lateinit var car3: Car

  @SpyK
  var car4 = Car()

  @Test
  fun calculateAddsValues1() {
      // ... use car1, car2, car3 and car4
  }
}
```
さらに、テスト関数のパラメーターで`@MockK`および`@RelaxedMockK`を使用する可能性が追加されます。

```kotlin
@Test
fun calculateAddsValues1(@MockK car1: Car, @RelaxedMockK car2: Car) {
  // ... use car1 and car2
}
```
## Spy
スパイはモックと実際のオブジェクトを混ぜることができます。

```kotlin
val car = spyk(Car()) // またはspyk <Car>（）でデフォルトのコンストラクターを呼び出します

car.drive(Direction.NORTH) // Carが返す実際の関数を返します

verify { car.drive(Direction.NORTH) }

confirmVerified(car)
```
注：スパイオブジェクトは、渡されたオブジェクトのコピーです。

## Relaxed mock

`relaxed mock`は、すべての関数に対して単純な値を返すモックです。これにより、各ケースの動作の指定をスキップしながら、必要なものをスタブ化できます。参照型の場合、連鎖モックが返されます。

```kotlin
val car = mockk<Car>(relaxed = true)

car.drive(Direction.NORTH) // returns null

verify { car.drive(Direction.NORTH) }

confirmVerified(car)
```
注：`relaxed mock`を使用する際は、戻り値がジェネリックではうまく機能しません。通常、この場合、クラスキャスト例外がスローされます。戻り値がジェネリックの場合、スタブを手動で指定する必要があります。

回避策：

```kotlin
val func = mockk<() -> Car>(relaxed = true) // この場合、invoke関数は戻り値にジェネリックを持ちます

// この行は回避策です。この行がないと`relaxed mock`は次の行でクラスキャスト例外をスローします
every { func() } returns Car() // または、例えばmockk()を返すことができます

func()
```

## Unitを返す関数のRelaxed mock(Mock relaxed for functions returning Unit)

Unitを返す関数を`Relaxed mock`にしたい場合は、`mockk`関数、`@MockK` アノテーションまたは`MockKAnntations.init`関数の引数として`relaxUnitFun = true`を使用できます。

`mockk`関数：

```kotlin
mockk<MockCls>(relaxUnitFun = true)
```
`@MockK` アノテーション：

```kotlin
@MockK(relaxUnitFun = true)
lateinit var mock1: RurfMockCls
init {
    MockKAnnotations.init(this)
}
```
`MockKAnntations.init`関数：

```kotlin
@MockK
lateinit var mock2: RurfMockCls
init {
    MockKAnnotations.init(this, relaxUnitFun = true)
}
```
## オブジェクトモック(Object mocks)
オブジェクトは次の方法でモックに変換できます。

```kotlin
object MockObj {
  fun add(a: Int, b: Int) = a + b
}

mockkObject(MockObj) // モックをオブジェクトに適用します

assertEquals(3, MockObj.add(1, 2))

every { MockObj.add(1, 2) } returns 55

assertEquals(55, MockObj.add(1, 2))
```
元に戻すには、`unmockkAll`または`unmockkObject`を使用します。

```kotlin
@Before
fun beforeTests() {
    mockkObject(MockObj)
    every { MockObj.add(1,2) } returns 55
}

@Test
fun willUseMockBehaviour() {
    assertEquals(55, MockObj.add(1,2))
}

@After
fun afterTests() {
    unmockkAll()
    // or unmockkObject(MockObj)
}
```

Kotlin言語の制限にもかかわらず、テストロジックで必要な場合は、オブジェクトの新しいインスタンスを作成できます。

```kotlin
val newObjectMock = mockk<MockObj>()
```

## クラスモック(Class mock)

時には、任意のクラスのモックが必要です。そのような場合にはmockkClassを使用してください。

```kotlin
val car = mockkClass(Car::class)

every { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

verify { car.drive(Direction.NORTH) }
```

## 列挙モック(Enumeration mocks)

列挙型は、`mockkObject`を使用してモックできます。

```kotlin
enum class Enumeration(val goodInt: Int) {
    CONSTANT(35),
    OTHER_CONSTANT(45);
}

mockkObject(Enumeration.CONSTANT)
every { Enumeration.CONSTANT.goodInt } returns 42
assertEquals(42, Enumeration.CONSTANT.goodInt)
```

## コンストラクタモック(Constructor mocks)

場合によっては、特に所有していないコードでは、新しく作成したオブジェクトをモックする必要があります。この目的のために、次の構成が提供されます。

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

mockkConstructor(MockCls::class)

every { anyConstructed<MockCls>().add(1, 2) } returns 4

assertEquals(4, MockCls().add(1, 2)) // 新しいオブジェクトが作成されることに注意してください

verify { anyConstructed<MockCls>().add(1, 2) }
```

基本的な考え方は、モックされたクラスのコンストラクタが実行された直後に、オブジェクトは`constructed mock`になるということです。そのようなモックのモッキング動作は、`anyConstructed<MockCls>()`で示される特別な`prototype mock`に接続されます。このような`prototype mock`のクラスごとに1つのインスタンスがあります。コールの記録は、`prototype mock`でも発生します。関数の動作が指定されていない場合、元の関数が実行されます。

## 部分引数マッチング(Partial argument matching)

通常の引数とマッチャーの両方を混在させることができます。

```kotlin
val car = mockk<Car>()

every { 
  car.recordTelemetry(
    speed = more(50),
    direction = Direction.NORTH, // ここで `eq()` が使用されます
    lat = any(),
    long = any()
  )
} returns Outcome.RECORDED

obj.recordTelemetry(60, Direction.NORTH, 51.1377382, 17.0257142)

verify { obj.recordTelemetry(60, Direction.NORTH, 51.1377382, 17.0257142) }

confirmVerified(obj)
```

## 連鎖呼び出し(Chained calls)

呼び出しのチェーンをスタブ化できます。

```kotlin
val car = mockk<Car>()

every { car.door(DoorType.FRONT_LEFT).windowState() } returns WindowState.UP

car.door(DoorType.FRONT_LEFT) // Doorの連鎖モックを返します
car.door(DoorType.FRONT_LEFT).windowState() // returns WindowState.UP

verify { car.door(DoorType.FRONT_LEFT).windowState() }

confirmVerified(car)
```
注：関数の戻り値の型がジェネリックである場合、実際の型に関する情報は消去されます。連鎖呼び出しを機能させるには、追加情報が必要です。ほとんどの場合、フレームワークはキャスト例外をキャッチし、`autohinting `を実行します。明示的に必要な場合は、次の呼び出しを行う前に`hint`を使用してください。

```kotlin
every { obj.op2(1, 2).hint(Int::class).op1(3, 4) } returns 5
```
## 階層的なモック(Hierarchical mocking)
バージョン1.9.1から、モックを階層にチェーンすることができます。

```kotlin
interface AddressBook {
    val contacts: List<Contact>
}

interface Contact {
    val name: String
    val telephone: String
    val address: Address
}

interface Address {
    val city: String
    val zip: String
}

val addressBook = mockk<AddressBook> {
    every { contacts } returns listOf(
        mockk {
            every { name } returns "John"
            every { telephone } returns "123-456-789"
            every { address.city } returns "New-York"
            every { address.zip } returns "123-45"
        },
        mockk {
            every { name } returns "Alex"
            every { telephone } returns "789-456-123"
            every { address } returns mockk {
                every { city } returns "Wroclaw"
                every { zip } returns "543-21"
            }
        }
    )
}
```

## キャプチャ(Capturing)
`CapturingSlot`または`MutableList`への引数をキャプチャできます。

```kotlin
val car = mockk<Car>()

val slot = slot<Double>()
val list = mutableListOf<Double>()

every {
  obj.recordTelemetry(
    speed = capture(slot),
    direction = Direction.NORTH
  )
} answers {
  println(slot.captured)

  Outcome.RECORDED
}


every {
  obj.recordTelemetry(
    speed = capture(list),
    direction = Direction.SOUTH
  )
} answers {
  println(list.captured())

  Outcome.RECORDED
}

obj.recordTelemetry(speed = 15, direction = Direction.NORTH) // prints 15
obj.recordTelemetry(speed = 16, direction = Direction.SOUTH) // prints 16

verify(exactly = 2) { obj.recordTelemetry(speed = or(15, 16), direction = any()) }

confirmVerified(obj)
```

## 最小、最大、または正確な回数の検証(Verification atLeast, atMost or exactly times)
呼び出しカウントは、`atLeast`、`atMost`、または`exactly`パラメーターで確認できます。

```kotlin
val car = mockk<Car>(relaxed = true)

car.accelerate(fromSpeed = 10, toSpeed = 20)
car.accelerate(fromSpeed = 10, toSpeed = 30)
car.accelerate(fromSpeed = 20, toSpeed = 30)

// すべて通ります
verify(atLeast = 3) { car.accelerate(allAny()) }
verify(atMost  = 2) { car.accelerate(fromSpeed = 10, toSpeed = or(20, 30)) }
verify(exactly = 1) { car.accelerate(fromSpeed = 10, toSpeed = 20) }
verify(exactly = 0) { car.accelerate(fromSpeed = 30, toSpeed = 10) } // 呼び出しが実行されなかったことを意味します

confirmVerified(car)
```

## 検証順序(Verification order)
- `verifyAll`は、順序を確認せずにすべての呼び出しが行われたことを検証します。
- `verifySequence`は、指定された順序で呼び出しが行われたことを検証します。
- `verifyOrder`は、呼び出しが特定の順序で発生したことを検証します。
- `wasNot Called`は、モックまたはモックのリストがまったく呼び出されなかったことを検証します。

```kotlin
class MockedClass {
    fun sum(a: Int, b: Int) = a + b
}

val obj = mockk<MockedClass>()
val slot = slot<Int>()

every {
    obj.sum(any(), capture(slot))
} answers {
    1 + firstArg<Int>() + slot.captured
}

obj.sum(1, 2) // returns 4
obj.sum(1, 3) // returns 5
obj.sum(2, 2) // returns 5

verifyAll {
    obj.sum(1, 3)
    obj.sum(1, 2)
    obj.sum(2, 2)
}

verifySequence {
    obj.sum(1, 2)
    obj.sum(1, 3)
    obj.sum(2, 2)
}

verifyOrder {
    obj.sum(1, 2)
    obj.sum(2, 2)
}

val obj2 = mockk<MockedClass>()
val obj3 = mockk<MockedClass>()
verify {
    listOf(obj2, obj3) wasNot Called
}

confirmVerified(obj)
```

## 検証確認(Verification confirmation)
`verify...`構文によってすべての呼び出しが検証されたことを再確認するには、`confirmVerified`を使用できます。

```kotlin
confirmVerified(mock1, mock2)
```

これらの検証メソッドは、検証付きのすべての呼び出しを網羅しているため、`verifySequence`および`verifyAll`に使用することはあまり意味がありません。

いくつかの呼び出しが検証なしで残っている場合、例外をスローします。

一部の呼び出しはこのような確認からスキップされる場合があります。詳細については次のセクションを確認してください。

```kotlin
val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK
every { car.drive(Direction.SOUTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK
car.drive(Direction.SOUTH) // returns OK

verify {
    car.drive(Direction.SOUTH)
    car.drive(Direction.NORTH)
}

confirmVerified(car) // すべての呼び出しが検証でカバーされたことを確認します
```
## 記録の除外(Recording exclusions)
それほど重要ではない呼び出しを記録から除外するには、`excludeRecords`を使用できます。

```kotlin
excludeRecords { mock.operation(any(), 5) }
```

一致するすべての呼び出しは記録から除外されます。これは、`verifyAll`、`verifySequence`、`confirmVerified`などの包括的な検証を使用している場合に役立ちます。

```kotlin
val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK
every { car.drive(Direction.SOUTH) } returns Outcome.OK

excludeRecords { car.drive(Direction.SOUTH) }

car.drive(Direction.NORTH) // returns OK
car.drive(Direction.SOUTH) // returns OK

verify {
    car.drive(Direction.NORTH)
}

confirmVerified(car) // car.drive(Direction.SOUTH)が除外されたため、car.drive(Direction.NORTH)のみで確認できます。
```
## 検証タイムアウト(Verification timeout)
同時操作を確認するには、`timeout = xxx`を使用できます。

```kotlin
mockk<MockCls> {
    every { sum(1, 2) } returns 4

    Thread {
        Thread.sleep(2000)
        sum(1, 2)
    }.start()

    verify(timeout = 3000) { sum(1, 2) }
}
```

これは、検証に合格するか、タイムアウトに達するかのいずれかの状態になるまで待機します。

## Unitを返却(Returning Unit)
関数が`Unit`を返す場合、`just Runs`を使用できます。

```kotlin
class MockedClass {
    fun sum(a: Int, b: Int): Unit {
        println(a + b)
    }
}

val obj = mockk<MockedClass>()

every { obj.sum(any(), 3) } just Runs

obj.sum(1, 1)
obj.sum(1, 2)
obj.sum(1, 3)

verify {
    obj.sum(1, 1)
    obj.sum(1, 2)
    obj.sum(1, 3)
}
```

## コルーチン(Coroutines)
コルーチンをモックするには、サポートライブラリに別の依存関係を追加する必要があります。

### Gradle

```gradle
testCompile "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x"
```
### Maven

```xml
<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-coroutines-core</artifactId>
    <version>x.x</version>
    <scope>test</scope>
</dependency>
```
次に、`coEvery`、`coVerify`、`coMatch`、`coAssert`、`coRun`、`coAnswers`、または`coInvoke`を使用して、中断関数をモックできます。

```kotlin
val car = mockk<Car>()

coEvery { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

coVerify { car.drive(Direction.NORTH) }
```

## 拡張関数(Extension functions)
拡張関数には3つのケースがあります。

- クラス全体(class wide)
- オブジェクト全体(object wide)
- モジュール全体(module wide)

オブジェクトとクラスの場合、通常のモックを作成するだけで拡張関数をモックできます。

```kotlin
data class Obj(val value: Int)

class Ext {
    fun Obj.extensionFunc() = value + 5
}

with(mockk<Ext>()) {
    every {
        Obj(5).extensionFunc()
    } returns 11

    assertEquals(11, Obj(5).extensionFunc())

    verify {
        Obj(5).extensionFunc()
    }
}
```

モジュール全体の拡張機能をモックするには、モジュールのクラス名を引数として`mockkStatic(...)`をビルドする必要があります。例えば、`pkg`パッケージのモジュール`File.kt`の"pkg.FileKt"。

```kotlin
data class Obj(val value: Int)

// File.kt（"pkg" パッケージ）で宣言されています
fun Obj.extensionFunc() = value + 5

mockkStatic("pkg.FileKt")

every {
    Obj(5).extensionFunc()
} returns 11

assertEquals(11, Obj(5).extensionFunc())

verify {
    Obj(5).extensionFunc()
}
```

`@JvmName`を使用する場合は、クラス名として指定します。

KHttp.kt：

```kotlin
@file:JvmName("KHttp")

package khttp
// ... KHttp code 
```

テストコード：

```kotlin
mockkStatic("khttp.KHttp")
```

拡張関数をモックするために、もう少し詳しく知る必要がある場合があります。たとえば、`File.endsWith()`拡張関数には、まったく予測できない`classname`があります。

```kotlin
mockkStatic("kotlin.io.FilesKt__UtilsKt")
every { File("abc").endsWith(any<String>()) } returns true
println(File("abc").endsWith("abc"))
```

これは、予測不能な標準的なKotlinの動作です。`[Tools]-> [Kotlin]-> [Show Kotlin Bytecode]`を使用するか、JARアーカイブ内の`.class`ファイルを確認して、このような名前を検出します。

## 可変引数(Varargs)
バージョン1.9.1から、さらに拡張された可変引数処理が可能になりました。

```kotlin
    interface ClsWithManyMany {
        fun manyMany(vararg x: Any): Int
    }

    val obj = mockk<ClsWithManyMany>()

    every { obj.manyMany(5, 6, *varargAll { it == 7 }) } returns 3

    println(obj.manyMany(5, 6, 7)) // 3
    println(obj.manyMany(5, 6, 7, 7)) // 3
    println(obj.manyMany(5, 6, 7, 7, 7)) // 3

    every { obj.manyMany(5, 6, *anyVararg(), 7) } returns 4

    println(obj.manyMany(5, 6, 1, 7)) // 4
    println(obj.manyMany(5, 6, 2, 3, 7)) // 4
    println(obj.manyMany(5, 6, 4, 5, 6, 7)) // 4

    every { obj.manyMany(5, 6, *varargAny { nArgs > 5 }, 7) } returns 5

    println(obj.manyMany(5, 6, 4, 5, 6, 7)) // 5
    println(obj.manyMany(5, 6, 4, 5, 6, 7, 7)) // 5

    every {
        obj.manyMany(5, 6, *varargAny {
            if (position < 3) it == 3 else it == 4
        }, 7)
    } returns 6
    
    println(obj.manyMany(5, 6, 3, 4, 7)) // 6
    println(obj.manyMany(5, 6, 3, 4, 4, 7)) // 6
```

## プライベート関数のモック / 動的呼び出し(Private functions mocking / dynamic calls)
プライベート関数をモックする必要がある場合は、動的呼び出しを介して行うことができます。

```kotlin
class Car {
    fun drive() = accelerate()

    private fun accelerate() = "going faster"
}

val mock = spyk<Car>(recordPrivateCalls = true)

every { mock["accelerate"]() } returns "going not so fast"

assertEquals("going not so fast", mock.drive())

verifySequence {
    mock.drive()
    mock["accelerate"]()
}
```
プライベート呼び出しを検証する場合は、`recordPrivateCalls = true`で`spyk`を作成する必要があります。

さらに、より詳細な構文により、同じ動的呼び出しと組み合わせてプロパティを取得および設定できます。

```kotlin
val mock = spyk(Team(), recordPrivateCalls = true)

every { mock getProperty "speed" } returns 33
every { mock setProperty "acceleration" value less(5) } just runs
every { mock invokeReturnsUnit "privateMethod" } just runs
every { mock invoke "openDoor" withArguments listOf("left", "rear") } returns "OK"

verify { mock getProperty "speed" }
verify { mock setProperty "acceleration" value less(5) }
verify { mock invoke "openDoor" withArguments listOf("left", "rear") }
```
## プロパティバッキングフィールド(Property backing fields)
`fieldValue`を介してフィールドバッキングプロパティにアクセスし、設定される値に`value`を使用できます。

注：以下の例では、`propertyType`を使用して`fieldValue`の型を指定しています。これは、ゲッターのタイプを自動的にキャプチャできるため、必要です。 `nullablePropertyType`を使用して、null許容型を指定します。

```kotlin
val mock = spyk(MockCls(), recordPrivateCalls = true)

every { mock.property } answers { fieldValue + 6 }
every { mock.property = any() } propertyType Int::class answers { fieldValue += value }
every { mock getProperty "property" } propertyType Int::class answers { fieldValue + 6 }
every { mock setProperty "property" value any<Int>() } propertyType Int::class answers  { fieldValue += value }
every {
    mock.property = any()
} propertyType Int::class answers {
    fieldValue = value + 1
} andThen {
    fieldValue = value - 1
}
```
## 複数のインターフェース(Multiple interfaces)
インターフェイスを介して追加の動作を追加し、それらをスタブ化します。

```kotlin
val spy = spyk(System.out, moreInterfaces = Runnable::class)

spy.println(555)

every {
    (spy as Runnable).run()
} answers {
    (self as PrintStream).println("Run! Run! Run!")
}

val thread = Thread(spy as Runnable)
thread.start()
thread.join()
```

## Mocking nothing
ここでは特別なことは何もありません。 Nothingを返す関数がある場合：

```kotlin
fun quit(status: Int): Nothing {
    exitProcess(status)
}
```

次に、たとえば、例外を動作としてスローできます。

```kotlin
every { quit(1) } throws Exception("this is a test")
```
# マッチャーの拡張性(Matcher extensibility)
非常に簡単な方法は、関数を`MockKMatcherScope`または`MockKVerificationScope`にアタッチし、`match`関数を使用して新しいマッチャーを作成することです。

```kotlin
fun MockKMatcherScope.seqEq(seq: Sequence<String>) = match<Sequence<String>> {
    it.toList() == seq.toList()
}
```
また、Matcherインターフェースを実装することにより、より高度なマッチャーを作成することもできます。

# 設定ファイル(Settings file)
パラメータをグローバルに調整するには、リソースファイルでいくつかの設定を指定します。

使い方： 
1. リソースに`io/mockk/settings.properties`ファイルを作成します。
2. 次のオプションのいずれかを入力します。

```properties
relaxed=true|false
relaxUnitFun=true|false
recordPrivateCalls=true|false
```

# DSLテーブル(DSL tables)

DSLを習得するのに役立ついくつかの表を次に示します。

## トップレベル関数(Top level functions)
| 関数       |       説明 |
|:-----------------|:------------------|
| `mockk<T>(...)`             |              通常のモックを作成します |
| `spyk<T>()`           |            デフォルトのコンストラクタを使用してスパイを構築します |
| `spyk(obj)`             |              `obj`からコピーしてスパイを構築します |
| `slot `               |                キャプチャスロットを作成します |
| `every `             |             スタブブロックを開始します |
| `coEvery `          |           コルーチンのスタブブロックを開始します |
| `verify `             |              検証ブロックを開始します |
| `coVerify `           |            コルーチンの検証ブロックを開始します |
| `verifyAll `             |              すべての呼び出しを含む検証ブロックを開始します |
| `coVerifyAll `               |                コルーチンのすべての呼び出しを含む検証ブロックを開始します |
| `verifyOrder `             |             順序を確認する検証ブロックを開始します |
| `coVerifyOrder `          |           コルーチンの順序を確認する検証ブロックを開始します |
| `verifySequence `             | すべての呼び出しが指定された順序で行われたかどうかを確認する検証ブロックを開始します |
| `coVerifySequence `           | コルーチンのすべての呼び出しが指定された順序で行われたかどうかを確認する検証ブロックを開始します |
| `excludeRecords `             |   呼び出しから一部の記録を除外する |
| `confirmVerified `               | 記録されたすべての呼び出しが検証されたことを確認します |
| `clearMocks `             |             指定されたモックをクリアします |
| `registerInstanceFactory `          |           特定のオブジェクトのインスタンス化の方法を再定義できます |
| `mockkClass `             | クラスをパラメーターとして渡すことにより、通常のモックを作成します |
| `mockkObject `           |            任意のオブジェクトをオブジェクトのモックにするか、すでに変換されている場合はクリアします |
| `unmockkObject `             | オブジェクトモックを通常のオブジェクトに戻します |
| `mockkStatic `               |  クラスから静的モックを作成するか、既に変換されている場合はクリアします |
| `unmockkStatic `             | 静的モックを通常のクラスに戻します |
| `clearStaticMockk `          | 静的モックをクリアします |
| `mockkConstructor `             | コンストラクタモックをクラスから外すか、すでに変換されている場合はクリアします |
| `unmockkConstructor `    |  コンストラクタモックを通常のクラスに戻します |
| `clearConstructorMockk `   |  コンストラクターのモックをクリアします |
| `unmockkAll `           | オブジェクトモック、静的モック、コンストラクタモックをアンモックします |
| `clearAllMocks `             | 通常のモック、オブジェクトモック、静的モック、コンストラクタモックをクリアします |

## マッチャー(Matchers)

デフォルトでは、単純な引数は`eq()`を使用して照合されます。

| マッチャー     |      説明 |
|:-----------------|:------------------|
| `any() `               |                任意の引数に一致します |
| `allAny() `             |    単純な引数として提供されるマッチャーに`eq()`の代わりに`any()`を使用する特別なマッチャーです |
| `isNull() `          |         値がnullかどうかをチェックします |
| `isNull(inverse=true) `             |   値がnullでないかどうかをチェックします |
| `ofType(type) `           |        値が型に属するかどうかを確認します |
| `match { it.startsWith("string") } `             |   渡された述部を介して一致します |
| `coMatch { it.startsWith("string") } `           |   渡されたコルーチン述部を介して一致します |
| `matchNullable { it?.startsWith("string") } `    |   渡された述部を介してnull許容値に一致します |
| `coMatchNullable { it?.startsWith("string") } `  |   渡されたコルーチン述部を介してnull許容値に一致します |
| `eq(value) `        |    値が`deepEquals`関数を介して提供された値と等しい場合に一致します |
| `eq(value, inverse=true) `           |  値が`deepEquals`関数を介して提供された値と等しくない場合に一致します |
| `neq(value) `             | 値が`deepEquals`関数を介して提供された値と等しくない場合に一致します |
| `refEq(value) `               |  値が参照比較によって提供された値と等しい場合に一致します |
| `refEq(value, inverse=true) ` |  値が参照比較によって提供された値と等しくない場合に一致します |
| `nrefEq(value) `          |      値が参照比較によって提供された値と等しくない場合に一致します |
| `cmpEq(value) `             |   値が`compareTo`関数で提供された値と等しい場合に一致します |
| `less(value) `           |      値が`compareTo`関数で指定された値より小さい場合に一致します |
| `more(value) `             |    値が`compareTo`関数で提供された値より大きい場合に一致します |
| `less(value, andEquals=true) `   |  値が`compareTo`関数で指定された値以下である場合に一致します |
| `more(value, andEquals=true) `   |  値が`compareTo`関数で指定された値以上である場合に一致します |
| `range(from, to, fromInclusive=true, toInclusive=true) `          |           `compareTo`関数を介して値が範囲内にある場合に一致します |
| `and(left, right) `             | 論理積で2つのマッチャーを結合します |
| `or(left, right) `           | 論理和で2つのマッチャーを結合します |
| `not(matcher) `             |   マッチャーを無効にします |
| `capture(slot) `               |  `CapturingSlot`に値をキャプチャします |
| `capture(mutableList) `             |    値をリストにキャプチャします |
| `captureNullable(mutableList) `  |  null値とともに値をリストにキャプチャします |
| `captureLambda() `             |  ラムダをキャプチャします |
| `captureCoroutine() `          | コルーチンをキャプチャします |
| `invoke(...) `             |  一致した引数を呼び出します |
| `coInvoke(...) `           | コルーチンの一致した引数を呼び出します |
| `hint(cls) `             | 消去された場合に備えて、次の戻り値のタイプを示します |
| `anyVararg() `               | 可変引数の任意の要素に一致します |
| `varargAny(matcher) `        |  いずれかの要素がマッチャーに一致する場合に一致します |
| `varargAll(matcher) `          | すべての要素がマッチャーに一致する場合に一致します |
| `any...Vararg() `  | 可変引数のすべての要素に一致します（プリミティブ型に固有） |
| `varargAny...(matcher) `       |  いずれかの要素がマッチャーに一致する場合に一致します（プリミティブ型に固有） |
| `varargAll...(matcher) `      |  すべての要素がマッチャーに一致する場合に一致します（プリミティブ型に固有） |

検証モードでのみ使用可能な特別なマッチャーがいくつかあります。

| マッチャー       |      説明 |
|:-----------------|:------------------|
| `withArg { code } `  | 任意の値に一致し、コードの実行を許可します |
| `withNullableArg { code } `  | null値を許可する値と一致し、コードの実行を許可します |
| `coWithArg { code } `       | 任意の値に一致し、コルーチンコードを実行できます |
| `coWithNullableArg { code } ` | null値を許可する値と一致し、コルーチンコードを実行できます |

## バリデーター(Validators)

| バリデーター       |       説明 |
|:-----------------|:------------------|
| `verify { mock.call() } `           | 呼び出しが実行されたことを順不同で検証します |
| `verify(inverse=true) { mock.call() } ` | 呼び出しが実行されなかったことを順不同で検証します |
| `verify(atLeast=n) { mock.call() } `          | 呼び出しが少なくともn回実行されたことを順不同で検証します |
| `verify(atMost=n) { mock.call() } `             |              呼び出しが最大n回実行されたことを順不同で検証します |
| `verify(exactly=n) { mock.call() } `           |            呼び出しが正確にn回実行されたことを順不同で検証します |
| `verifyAll { mock.call1(); mock.call2() } `             |              言及されたモックに対して指定された呼び出しのみが実行されたことを順不同で検証します |
| `verifyOrder { mock.call1(); mock.call2() } `               |                指定した順序で呼び出しが次々に行われたことを検証します |
| `verifySequence { mock.call1(); mock.call2() } `             |             言及されたモックに対して、指定された一連の呼び出しのみが実行されたことを検証します |
| `verify { mock wasNot Called }	 `          |           モックが呼び出されなかったことを検証します |
| `verify { listOf(mock1, mock2) wasNot Called } `             |              モックのリストが呼び出されなかったことを検証します |

## アンサー(Answers)

アンサーの後に、1つ以上の追加のアンサーが続く場合があります。

| アンサー     |      説明 |
|:-----------------|:------------------|
| `returns value `               |   一致した呼び出しが指定された値を返すことを指定します |
| `returnsMany list `             | 一致した呼び出しがリストから値を返し、後続の呼び出しが次の要素を返すことを指定します|
| `throws ex `          |   一致した呼び出しが例外をスローすることを指定します |
| `answers { code } `             |    一致した呼び出しが`answer scope`を持つコードブロックで応答することを指定します |
| `coAnswers { code } `           |   一致した呼び出しが`answer scope`を持つコルーチンコードブロックで応答することを指定します |
| `answers answerObj `             |  一致した呼び出しがAnswerオブジェクトで応答することを指定します |
| `answers { nothing } `        | 一致した呼び出しがnullに応答することを指定します |
| `just Runs `   |  一致した呼び出しがUnitを返すことを指定します（nullを返します） |
| `propertyType Class `          |   バッキングフィールドアクセサの型を指定します |
| `nullablePropertyType Class `             |  バッキングフィールドアクセサの型をnull許容型として指定します |

## 追加のアンサー(Additional answer)

結果として生じる各呼び出しで次のアンサーが返され、最後の値が保持されます。これは、`returnsMany`セマンティクスに似ています。

| 追加のアンサー       |      説明 |
|:-----------------|:------------------|
| `andThen value `               |                一致した呼び出しが1つの指定された値を返すことを指定します |
| `andThenMany list `             |             一致した呼び出しがリストから値を返し、次の要素が返されるたびに返すことを指定します |
| `andThenThrows ex `          |    一致した呼び出しが例外をスローすることを指定します |
| `andThen { code } `             |  一致した呼び出しが`answer scope`でスコープされたコードブロックで応答することを指定します |
| `coAndThen { code } `           |  一致した呼び出しが`answer scope`でスコープされたコルーチンコードブロックで応答することを指定します |
| `andThenAnswer answerObj `   |   一致した呼び出しがAnswerオブジェクトで応答することを指定します |
| `andThen { nothing } `    |   一致した呼び出しがnullに応答することを指定します |

## アンサースコープ(Answer scope)

| パラメータ   |      説明 |
|:-----------------|:------------------|
| `call `               |    呼び出しとマッチャーで構成される呼び出しオブジェクト |
| `invocation `         |  呼び出された実際の関数に関する情報が含まれています |
| `matcher `          | 呼び出しの照合に使用されるマッチャーに関する情報が含まれています |
| `self `             |  呼び出されたオブジェクトを参照します |
| `method `           |  呼び出された関数を参照します |
| `args `             |  呼び出す引数を参照します |
| `nArgs `               | 呼び出す引数の数 |
| `arg(n) `             |  n番目の引数 |
| `firstArg() `           |  第一引数 |
| `secondArg() `          |  第二引数 |
| `thirdArg() `           |  第三引数 |
| `lastArg() `             |  最後の引数 |
| `captured() `           |  リストにキャプチャするときに便利なリストの最後の要素 |
| `lambda<...>().invoke() `     |  キャプチャされたラムダを呼び出す |
| `coroutine<...>().coInvoke() `          |   キャプチャされたコルーチンを呼び出す |
| `nothing `             |        答えとして何も返さない場合はnull値 |
| `fieldValue `           |       プロパティバッキングフィールドへのアクセサ |
| `fieldValueAny `        |  `Any?`型を持つプロパティバッキングフィールドへのアクセサ |
| `value `               |   プロパティバッキングフィールドと同じ型にキャストされる値 |
| `valueAny `             |  `Any?`型で設定されている値 |

## 可変引数スコープ(Vararg scope)

| パラメータ     |       説明 |
|:-----------------|:------------------|
| `position `               |       可変引数配列の引数の位置 |
| `nArgs `             |            可変引数配列の引数の総数 |

# おわりに
公式ドキュメントでは使用例が掲載されていない機能も多数あるので、GitHubのサンプルコードからも引っ張ってこようと思ってます。

終盤、心が折れそうになりました。
スラスラとUnit Test書けるようになりたい。（大抵なにかしらで躓いてます...）