2013-06-11 26 views
8

Tôi đang sử dụng peridot - https://github.com/xeqi/peridot để kiểm tra ứng dụng chiếc nhẫn của tôi, và làm việc của nó tốt cho đến khi tôi cố gắng thử một yêu cầu bài với dữ liệu json:làm thế nào để tôi giả lập một yêu cầu bài json trong vòng?

 
(require '[cheshire.core :as json]) 
(use 'compojure.core) 

(defn json-post [req] 
    (if (:body req) 
    (json/parse-string (slurp (:body req))))) 

(defroutes all-routes 
    (POST "/test/json" req (json-response (json-post req)))) 

(def app (compojure.handler/site all-routes)) 

(use 'peridot.core) 

(-> (session app) 
    (request "/test/json" 
      :request-method :post 
      :body (java.io.ByteArrayInputStream. (.getBytes "hello" "UTF-8"))) 

cho IOException: stream closed.

Có cách nào tốt hơn để thực hiện việc này không?

Trả lời

9

TLDR:

(-> (session app) 
    (request "/test/json" 
      :request-method :post 
      :content-type "application/json" 
      :body (.getBytes "\"hello\"" "UTF-8"))) 

Khi peridot tạo ra một bản đồ theo yêu cầu nó sẽ mặc định application/x-www-form-urlencoded cho content-type cho một yêu cầu :post. Với ứng dụng như được chỉ định wrap-params (được bao gồm bởi compojure.handler/site) sẽ cố gắng đọc :body để phân tích cú pháp bất kỳ thông số nào được mã hóa dạng url. Sau đó, json-post cố gắng đọc lại số :body. Tuy nhiên InputStream s được thiết kế để đọc một lần và điều đó gây ra ngoại lệ.

Về cơ bản có hai cách để giải quyết vấn đề:

  1. Di compojure.handler/site.
  2. Thêm một loại nội dung theo yêu cầu (như thực hiện trong TLDR)
4
(require '[cheshire.core :as json]) 

(-> (session app) 
    (request "/test/json" 
      :request-method :post 
      :content-type "application/json" 
      :body (json/generate-string data)) 

Không cần phải gọi .getBytes, chỉ cần vượt qua json với :body tham số.