Integrantを使ったアプリケーションのテストとモックについて
自己紹介ayato-p.icon
みんなご存知あやぴーさんです。
今日話すこと
簡単なモックオブジェクトの作り方
ふつうにIntegrantを使ってモックを書いてみる
設定ファイルはこんな感じのときに
code:clojure
(def ^:private config
{:app/database
{:spec {:host "localhost" :port 5432}}
:app/server
{:endpoint (ig/ref :app/endpoint)
:opts {:host "localhost" :port 3000}}
:app/endpoint
{:routes
{"/users" (ig/ref :app.handler/user)}
:middlewares
:app.handler/user
{:database (ig/ref :app/database)}
:app.middleware/not-found
{}})
テストはこんな感じになる
code:clojure
;; ①
(defmethod ig/init-key :mock/database _
(shrubbery/mock
core/User
(defmethod ig/halt-key! :mock/database _)
(derive :mock/database :app/database)
(t/deftest user-handler-test
(t/testing "ユーザーハンドラーをテストする"
(let [system (-> (conf/read-config)
;; ②
(dissoc :app/database)
(assoc :mock/database {})
handler (:app.handler/user system)
;; ③
database (val (ig/find-derived-1 system :app/database))]
(t/is (= {:status 200
(handler {})))
(t/is (shrubbery/received? database core/users)))))
Kotlinに出会った
Kotlinにはmockkというモックライブラリがある
その書き心地を見てClojureでも出来ると嬉しい気がした
MockKこんな感じ
code:kotlin
@Test
fun テスト() {
every { ... } returns ...
doSomething()
verify { ... }
}
つまり…
テストに閉じたモックを作りたい
bulkheadを使ってモックを書いてみる
code:clojure
(b/set-prep! (constantly (conf/read-config)))
(t/deftest user-handler-test2
(t/testing "ユーザーハンドラーをテストする"
(b/with-bulkhead [handler :app.handler/user
database :app/database]
{:app/database (fn _
(println "Start mock database...")
(shrubbery/mock
core/User
(t/is (= {:status 200
(handler {})))
(t/is (shrubbery/received? database core/users)))))
番外編
code:clojure
(t/deftest user-handler-test3
(t/testing "ユーザーハンドラーをテストする"
(let [database (shrubbery/mock
core/User
handler (core/user-handler-constructor {:database database})]
(t/is (= {:status 200
(handler {})))
(t/is (shrubbery/received? database core/users)))))