测试期间胭脂红连接错误
Carmine connection error during tests
我有一个 luminus 项目,其中包含一些简单的 compojure-api 路线。
我添加了 carmine
来与 Redis 服务器通信,使用 wcar*
宏(在 services.clj 中定义)调用它,一切正常。
现在我正在尝试添加一些测试,但似乎 redis 连接在测试期间无法正常工作,因为我收到此错误 lein test
:
ERROR Carmine connection error
clojure.lang.ExceptionInfo: Carmine connection error {}
由于它在 dev
e prod
环境中工作,我认为这与 test
环境中缺少 env
负载有关,但我没有找不到解决方法。
这些是正在使用的代码的相关部分:
test.clj
(ns app.test.handler
(:require [clojure.test :refer :all]
[ring.mock.request :refer :all]
[app.handler :refer :all]))
(deftest test-app
(testing "redis ping"
(let [response ((app) (request :get "/api/redis-ping"))]
(is (= 200 (:status response))))))
services.clj
(ns app.routes.services
(:require [ring.util.http-response :refer :all]
[compojure.api.sweet :refer :all]
[schema.core :as s]
[app.config :refer [env]]
[clojure.tools.logging :as log]
[mount.core :refer [defstate]]
[taoensso.carmine :as car :refer (wcar)]))
(defmacro wcar* [& body] `(car/wcar
{:spec {:host (:redis-host env) :port (:redis-port env)}}
~@body))
(defapi service-routes
(context "/api" []
:tags ["myapi"]
(GET "/redis-ping" []
:return String
:summary "A redis client test."
(ok (wcar* (car/ping "hello"))))))
handler.clj
(ns app.handler
(:require [compojure.core :refer [routes wrap-routes]]
[app.routes.services :refer [service-routes]]
[compojure.route :as route]
[app.env :refer [defaults]]
[mount.core :as mount]
[app.middleware :as middleware]))
(mount/defstate init-app
:start ((or (:init defaults) identity))
:stop ((or (:stop defaults) identity)))
(def app-routes
(routes
#'service-routes
(route/not-found
"page not found")))
(defn app [] (middleware/wrap-base #'app-routes))
Profiles.clj
{:profiles/dev {:env {:redis-host "127.0.0.1" :redis-port 6381}}
:profiles/test {:env {:redis-host "127.0.0.1" :redis-port 6381}}}
Config.clj
(ns app.config
(:require [cprop.core :refer [load-config]]
[cprop.source :as source]
[mount.core :refer [args defstate]]))
(defstate env :start (load-config
:merge
[(args)
(source/from-system-props)
(source/from-env)]))
解决方案
使用测试前执行的 mount/start
命令添加一个文本夹具。
添加到test.clj:
(defn my-test-fixture [f]
(mount/start)
(f))
(use-fixtures :once my-test-fixture)
您正在使用 mount
来管理您的应用程序状态生命周期。我认为您没有在测试中调用 (mount/start)
因此您的 app.config/env
状态未正确初始化。另一方面,当您启动应用程序时,可能会调用 (mount/start)
,因此它可以正常工作。
我有一个 luminus 项目,其中包含一些简单的 compojure-api 路线。
我添加了 carmine
来与 Redis 服务器通信,使用 wcar*
宏(在 services.clj 中定义)调用它,一切正常。
现在我正在尝试添加一些测试,但似乎 redis 连接在测试期间无法正常工作,因为我收到此错误 lein test
:
ERROR Carmine connection error
clojure.lang.ExceptionInfo: Carmine connection error {}
由于它在 dev
e prod
环境中工作,我认为这与 test
环境中缺少 env
负载有关,但我没有找不到解决方法。
这些是正在使用的代码的相关部分:
test.clj
(ns app.test.handler
(:require [clojure.test :refer :all]
[ring.mock.request :refer :all]
[app.handler :refer :all]))
(deftest test-app
(testing "redis ping"
(let [response ((app) (request :get "/api/redis-ping"))]
(is (= 200 (:status response))))))
services.clj
(ns app.routes.services
(:require [ring.util.http-response :refer :all]
[compojure.api.sweet :refer :all]
[schema.core :as s]
[app.config :refer [env]]
[clojure.tools.logging :as log]
[mount.core :refer [defstate]]
[taoensso.carmine :as car :refer (wcar)]))
(defmacro wcar* [& body] `(car/wcar
{:spec {:host (:redis-host env) :port (:redis-port env)}}
~@body))
(defapi service-routes
(context "/api" []
:tags ["myapi"]
(GET "/redis-ping" []
:return String
:summary "A redis client test."
(ok (wcar* (car/ping "hello"))))))
handler.clj
(ns app.handler
(:require [compojure.core :refer [routes wrap-routes]]
[app.routes.services :refer [service-routes]]
[compojure.route :as route]
[app.env :refer [defaults]]
[mount.core :as mount]
[app.middleware :as middleware]))
(mount/defstate init-app
:start ((or (:init defaults) identity))
:stop ((or (:stop defaults) identity)))
(def app-routes
(routes
#'service-routes
(route/not-found
"page not found")))
(defn app [] (middleware/wrap-base #'app-routes))
Profiles.clj
{:profiles/dev {:env {:redis-host "127.0.0.1" :redis-port 6381}}
:profiles/test {:env {:redis-host "127.0.0.1" :redis-port 6381}}}
Config.clj
(ns app.config
(:require [cprop.core :refer [load-config]]
[cprop.source :as source]
[mount.core :refer [args defstate]]))
(defstate env :start (load-config
:merge
[(args)
(source/from-system-props)
(source/from-env)]))
解决方案
使用测试前执行的 mount/start
命令添加一个文本夹具。
添加到test.clj:
(defn my-test-fixture [f]
(mount/start)
(f))
(use-fixtures :once my-test-fixture)
您正在使用 mount
来管理您的应用程序状态生命周期。我认为您没有在测试中调用 (mount/start)
因此您的 app.config/env
状态未正确初始化。另一方面,当您启动应用程序时,可能会调用 (mount/start)
,因此它可以正常工作。