実装と方針
実装コード
@Component
class PersonsUsecase(
private val personPort: PersonPort,
) {
fun getAllPersons():Persons {
return personPort.getAllPersons()
}
テストをする対象のコードはこれ
At Component で外部から使えるようにして
同じく At Component で外部から使えるようになっている
Port とその先の Gateway の getAllPersons を呼んで
Persons ドメインで受け取って、そのまま Rest に返す。
方針
TDD をやりたい。だから単体テストを先に書く。
実装のように Gateway のインスタンスをそのまま呼び出して使うと
Usecase の単体テストなのに、Gateway も同時にテストすることになってしまう。
それは Clean Archtechture な TDD ではない。
Rest のテストが通って、Usecase のテストが通って、そのあとに Gateway を実装したい。
なので Gateway を呼び出すための Port を mockk を用いてモックにする。
単体テスト
実際にやること
Port の偽物の中身を読んだ時にできる想定物と
Usecase の中身を読んだ時に成果物
これらが同じか比較する。
単体テストコード全体
import io.mockk.*
import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.Test
class PersonsUsecaseTest {
@Test
fun `全てのPersonを取得する`() {
val persons = mockk<Persons>()
val personPort = mockk<PersonPort>()
val target = PersonsUsecase(personPort)
every { personPort.getAllPersons() } returns persons
val actual = target.getAllPersons()
actual shouldBeEqualTo persons
}
}
関数はじめと返り値のモック
@Test
fun `全てのPersonを取得する`() {
val persons = mockk<Persons>()
At Test でテストコードだということを明記。
mockk で Persons 型の偽物インスタンスを作成。これは単純。
Port のモックの中身を呼び出す
同じく mockk で PersonPort 型のインスタンスを作成する。
しかし、これは中身のメソッドを呼び出されることになる。
val personPort = mockk<PersonPort>()
target.getAllPersons()
たとえばこのまま mockk の偽物の中身を実装と同じ用に呼び出すと
no answer found for: PersonPort(#2).getAllPersons()
io.mockk.MockKException: no answer found for:
PersonPort(#2).getAllPersons()
PersonPort は mockk で作られた偽物である。
なので中身が呼び出せない。MockKException が起きる
Port のモックの中身を呼び出した時に何が返ってくるか決める
every { personPort.getAllPersons() } returns persons
ここで every { mockPort.functionName() } returns expectedMockName を使う。
すると {} 内部で Port のモックの中身の関数が呼ばれた時に
returns の後ろに書いた期待されるモックを返すようになる。
usecase として本体のインスタンスを呼び出す
val target = PersonsUsecase(personPort)
mock の port を usecase のクラスに渡してインスタンス化する。
Usecase 自体をモックにするのは次回。
まとめ
Usecase の UT を書くには
@Test
fun `シナリオ名`() {
と書き始めて
返り値の型の Domain のモックを用意。
内部で使われる Port のモックを用意。
every {} return で Port のモックの使用される関数が呼ばれた場合
Domain のモックが返されるように設定する
Port のモックを使って Usecase のインスタンスを作る
usecase のインスタンスの使用される関数が呼ばれた場合
Port のモックの中身が呼ばれた場合と同一結果になるか比較する。
以上。
次回
Usecase も本物に限りなく近いモックを用意してテストするようにする。
Top comments (0)