Kotlin Springboot -- Part 19 Rest と Domain の UT を作る
Tags: kotlin, ca
Published: 2022-12-04 17:33:29


## why

```kotlin
    @Test
    fun `指定した年齢未満のPersonsを取得する`() {
        MockKAnnotations.init(this)
        val allPersons = mockk<Persons>()
        every { port.getAllPersons() } returns allPersons
        val age = mockk<Age>()
        val expected = mockk<Persons>()
        every { allPersons.filterByLessThan(age) } returns expected
        target.getPersonsLessThanByAge(age) shouldBeEqualTo expected
    }
```

前回は Usecase で引数の数値未満の年齢の人間を取ってくるメソッドの UT を作った。

これは Gateway から取ってきた全ての Persons で、ドメインメソッドを呼び出し、結果が every で入ったドメインメソッドの返り値になっていることだけをテストしている。

これは Domain のメソッドの呼び出しがされるかどうかのテストまでしかしていない。

Domain のメソッドの動作のテストをするためには、Domain の UT を別に作る必要が有る。

---

## Domain の実装を見る

Domain の実装は

```kotlin
data class Persons(val list: List<Person>) {
  fun filterByLessThan(age: Age): Persons {
    return Persons(this.list.filter { it.isLessThan(age) })
  }
}

data class Person(val name: Name, val age: Age) {
  fun isLessThan(age: Age): Boolean {
    return this.age.isLessThan(age)
  }
}

data class Name(val value: String)

data class Age(val value: Int) {
  fun isLessThan(other: Age): Boolean {
    return this.value < other.value
  }
}
```

* Persons
  * Person
    * Age
      * isLessThan

と言う構造になっていて、Age のデータクラスに実際の処理が入っている。

---

## Domain の UT を作る

```kotlin
    testImplementation("org.amshove.kluent:kluent:1.68")
    testImplementation("io.mockk:mockk:1.13.2")
```

kluent と mockk を Domain にも追加

```kotlin
    @Test
    fun `受け取ったAge未満のPersonsを返す`() {
        val target = Persons(listOf(
            Person(Name("Taro"),Age(10)),
            Person(Name("Jiro"),Age(7)),
            Person(Name("Saburo"),Age(5)),
        ))
        val actual = target.filterByLessThan(Age(7))
        val expected = Persons(listOf(
            Person(Name("Saburo"),Age(5)),
        ))
        actual shouldBeEqualTo expected
    }
```

実際に返ってくるような 10,7,5 歳のデータが入った Persons を用意
これをターゲットとして filterByLessThan が使われた後
期待値の 5 歳のデータのみがはいった Persons になることをテストする 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfg12sp657crhkob005q.png)

---

## Rest で UT を作る

エンドポイントにリクエストされた結果のテストは外部からやる。

なので Rest の UT では Domain から JSON への変換のテストだけをする。

他と同様に mockk と kluent を入れて

```kotlin
internal class PersonResourceKtTest {

    @Test
    fun `PersonsをPersonJsonのリストに変換する`() {
        val target = Persons(listOf(
            Person(Name("Taro"),Age(10)),
            Person(Name("Jiro"),Age(7)),
        ))
        val actual = target.toJson()
        val expected = PersonsJson(
            listOf(
                PersonJson("Taro", 10),
                PersonJson("Jiro", 7),
            )
        )
        actual shouldBeEqualTo expected
    }
}
```

Person ドメインのリストである Persons を
PersonJson のリストである PersonsJson の形に変更できているかをテストする。

---

## これまでの UT のまとめ

### Driver

外部 API へのリクエストや DB へのアクセス。
E2E を流した時にテストされるので十分なので UT は必要ない。

### Gateway

Driver から返ってきた Entity の Domain への変換。
返ってきたデータの Usecase に応じたフィルターなど。

これらを Driver からの返り値を擬似的に決めて
最終的に指定の Domain の想定するフィルター後などの値になっているかをテストする。

### Port

穴にテストはない。

### Usecase

Gateway を呼び出すだけのテストをする

関数本体を呼び出した時に、port から gateway が呼ばれているかをテストする。

### Rest

URL からのアクセスで何が動くかはテストしない。
URL へのアクセスで DB や 外部への POST が飛ぶのは、E2E でテストされるからだ。

内部の Domain 型と 外部用の JSON 型の変換をテストする。


以上。