Clojure 如何使用ring.mock.request模拟PUT请求

Clojure 如何使用ring.mock.request模拟PUT请求,clojure,mocking,put,ring,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

如何通过此测试:

(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.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
这就是我在考试中试图嘲弄的。非常感谢您的帮助。

如果您想在您的
放置/设置/:id
路由接受主体中使用格式为
{“value”:“…”}
:id
,您需要更改路由定义: 并更改在测试中调用
PUT
端点的方式:

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

  • :id
    在您的
    PUT
    URL路由定义中(
    /settings
    ->
    /settings/:id
  • 您的
    PUT
    请求未发送正确的请求和内容类型
  • 如果希望有一个
    PUT/settings
    路由,该路由需要
    {“id”:“…”,“value”:“…”}
    请求正文,则需要更改创建模拟请求的方式:
    curl请求在PUT请求体中将参数指定为JSON,但mock请求尝试使用URL参数

    有两个选项可以解决此问题:

    • compojure可以自动转换参数,但只有当相关的中间件存在时——您的处理程序中添加了
      wrap json参数
      ,但缺少了。Piotrek Bzdyl的回答相当于在compojure路由中明确这些参数
    • 或者,您可以使用在模拟请求主体中添加ID/值对作为JSON

    放置/设置应如何工作?它在URL中是否有id`或作为JSON请求正文的一部分?理想情况下是按URL进行id,例如,浏览时会给出“FOO”。我修复了您的格式设置,特别是关于括号的位置。可能您正在使用的编辑器无法帮助您查看代码的结构,因此无法理解parens。试着用一个能帮你的。此外,还应尽量遵守通常的格式约定(例如,右括号前不能有空格),这样人们就更容易看到结构——你会很快习惯于在没有括号的情况下看到结构。非常非常有帮助,谢谢。最后一个代码位缺少括号。
    (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"))
    
    (w/app 
      (-> (mock/request
            :put
            "/settings/coordinateName"
            (json/generate-string {:value "FOO"}))
          (mock/content-type "application/json")))
    
    (w/app 
      (-> (mock/request
            :put
            "/settings"
            (json/generate-string {:id "coordinateName" :value "FOO"}))
          (mock/content-type "application/json"))