如何使用ring.mock.request

时间:2016-04-01 07:38:54

标签: clojure mocking put ring

如何通过此测试:

(ns imp-rest.parser-test-rest
  (:require [clojure.test :refer :all])
  (:require [ring.mock.request :as mock] )
  (:require [imp-rest.web :as w]))

(deftest test-parser-rest
  (testing "put settings"          
           (w/app 
             (mock/request :put "/settings/coordinateName" "FOO" ))

           (let [response (w/app (mock/request :get "/settings"))]
             (println response )
             (is (=  (get (:body response) :coordinateName) "FOO")))))

它失败了:

FAIL in (test-parser-rest) (parser_test_rest.clj:30)
put settings
expected: (= (get (:body response) :coordinateName) "FOO")
  actual: (not (= nil "FOO"))

这是我的处理程序:

(ns imp-rest.web
  (:use compojure.core)
  (:use ring.middleware.json-params)
  (:require [clj-json.core :as json])
  (:require [ring.util.response :as response])
  (:require [compojure.route :as route])
  (:require [imp-rest.settings :as s]))

(defn json-response [data & [status]]
   {:status (or status 200)
    :headers {"Content-Type" "application/json"}
    :body (json/generate-string data)}) 

(defroutes handler

   (GET "/settings" []
        (json-response (s/get-settings)))

   (GET "/settings/:id" [id]
        (json-response (s/get-setting id)))

   (PUT "/settings" [id value]
        (json-response (s/put-setting id value)))

   (route/not-found "Page not found") )

(def app
  (-> handler
    wrap-json-params))

公开此地图(设置):

(ns imp-rest.settings)

(def settings 
  (atom 
    {:coordinateName nil
     :burnin nil
     :nslices nil
     :mrsd nil
     }))

(defn get-settings []
  @settings) 

(defn get-setting [id]
  (@settings (keyword id))) 

(defn put-setting [id value]
  (swap! settings assoc (keyword id) value)
  value) 

和切入点:

(ns imp-rest.core
  (:use ring.adapter.jetty)
  (:require [imp-rest.web :as web]))

(defn -main
  "Entry point"
  [& args]
  (do        
    (run-jetty #'web/app {:port 8080})
    );END;do
  );END: main

现在,当我'lein run'时,我可以提出这样的(工作)请求:

curl -X PUT -H "Content-Type: application/json" \
    -d '{"id" : "coordinateName", "value" : "FOO"}' \
    http://localhost:8080/settings

这是我尝试用测试模拟的东西。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

如果您希望:id路由接受正文中的PUT /settings/:id格式为{"value": "..."},则需要更改路由定义:

(defroutes handler

  (GET "/settings" []
    (json-response (s/get-settings)))

  (GET "/settings/:id" [id]
    (json-response (s/get-setting id)))

  (PUT "/settings/:id" [id value]
    (json-response (s/put-setting id value)))

  (route/not-found "Page not found"))

并更改您在测试中调用PUT端点的方式:

(w/app 
  (-> (mock/request
        :put
        "/settings/coordinateName"
        (json/generate-string {:value "FOO"}))
      (mock/content-type "application/json")))

改变了什么?

    您的:id网址路线定义中的
  1. PUT/settings - > /settings/:id
  2. 您的PUT请求未发送正确的请求和内容类型。
  3. 如果您希望PUT /settings路由期望{"id": "...", "value": "..."}请求正文,则需要更改创建模拟请求的方式:

    (w/app 
      (-> (mock/request
            :put
            "/settings"
            (json/generate-string {:id "coordinateName" :value "FOO"}))
          (mock/content-type "application/json"))
    

答案 1 :(得分:2)

您的curl请求在PUT请求的正文中将参数指定为JSON,但您的模拟请求尝试使用URL参数。

有两种方法可以解决这个问题:

  • compojure可以自动转换参数,但只有当相关的中间件存在时 - 您已将wrap-json-params添加到您的处理程序中,但您缺少wrap-params。 Piotrek Bzdyl的答案相当于在组合路线中明确指出这些参数。
  • 或者,您可以使用request.mock.body在模拟请求的正文中将ID /值对添加为JSON。