Testing 具有防伪和环形模拟的测试柱路线
我想使用Testing 具有防伪和环形模拟的测试柱路线,testing,clojure,mocking,csrf,ring,Testing,Clojure,Mocking,Csrf,Ring,我想使用ring.mock,为一个简单的POST请求编写一个测试,如下所示: (testing "id post route" (let [response (app (mock/request :post "/" {:id "Foo"}))] (is (= 302 (:status response))))) 然而,由于我使用wrap csrf中间件,我得到了403状态响应,因为我没有提供防伪令牌 有没有一种方法可以在不禁用wrap csrf中间件的情况下使用ring.m
ring.mock
,为一个简单的POST请求编写一个测试,如下所示:
(testing "id post route"
(let [response (app (mock/request :post "/" {:id "Foo"}))]
(is (= 302 (:status response)))))
然而,由于我使用wrap csrf
中间件,我得到了403状态响应,因为我没有提供防伪令牌
有没有一种方法可以在不禁用
wrap csrf
中间件的情况下使用ring.mock
编写POST测试?您想测试什么?您的问题并不清楚,也不清楚为什么不应该禁用防伪中间件
处理程序
逻辑,请在不使用包装式“基础设施”中间件的情况下进行测试。如果您不能在测试中将防伪中间件应用于处理程序函数,并且问题消失,那么模拟防伪中间件就没有意义了首先,我想在此回应另一篇文章中关于方法和推理的一些观点:
app
,但是如果需要,您可以绕过CSRF直接测试端点。这将允许您测试给定端点,但无法测试CSRF保护是否正常工作(ns myapp.test.handler-test
(:require [clojure.test :refer :all]
[ring.mock.request :refer [request]]
[net.cgrand.enlive-html :as html]
[myapp.handler :refer [app]]))
(defn get-session
"Given a response, grab out just the key=value of the ring session"
[resp]
(let [headers (:headers resp)
cookies (get headers "Set-Cookie")
session-cookies (first (filter #(.startsWith % "ring-session") cookies))
session-pair (first (clojure.string/split session-cookies #";"))]
session-pair))
(defn get-csrf-field
"Given an HTML response, parse the body for an anti-forgery input field"
[resp]
(-> (html/select (html/html-snippet (:body resp)) [:input#__anti-forgery-token])
first
(get-in [:attrs :value])))
(defn get-login-session!
"Fetch a login page and return the associated session and csrf token"
[]
(let [resp (app (request :get "/login"))]
{:session (get-session resp)
:csrf (get-csrf-field resp)}))
(defn login!
"Login a user given a username and password"
[username password]
(let [{:keys [csrf session]} (get-login-session!)
req (-> (request :post "/login")
(assoc :headers {"cookie" session})
(assoc :params {:username username
:password password})
(assoc :form-params {"__anti-forgery-token" csrf}))]
(app req)
session))
在上面,我假设/login
页面使用\uuu-anti-forgery-token
隐藏输入,并且您希望对此进行测试。您还可以考虑将CSRF令牌放置在会话数据中,这样就更容易用诸如<代码> CURL< /COD>之类的工具进行测试,这样可以将会话数据从一个响应保存到一个文件中,以便在后续请求中使用。
因为我要从HTML主体中提取标记,所以我决定使用enlive
,这样我就可以使用CSS选择器以一种简单且声明性的方式定义从何处提取这些数据
要使用上述功能,您可以调用login
然后使用它在您希望通过同一会话进行身份验证的连续请求中返回的会话数据,例如:
(deftest test-home-page-authentication
(testing "authenticated response"
(let [session (login! "bob" "bob")
request (-> (request :get "/")
(assoc :headers {"cookie" session}))]
(is (= 200 (:status (app request)))))))
这假设您在使用的任何身份验证后端中都设置了用户名/密码bob和bob。您可能需要有一个用户名/密码设置步骤来创建此用户,然后此登录过程才能工作。我们可以使用
在测试中禁用csrf
(assoc site defaults:security false)
。完整的代码如下所示:
(testing "id post route"
(let [response (app (mock/request :post "/" {:id "Foo"}))]
(is (= 302 (:status response)))))
;在utilities.testing中创建测试应用程序的副本
; 通过使用测试中间件包装处理程序
(ns.测试
(:require[your-web-app.handler:参考[path handler]]
[ring.middleware.defaults:参考[wrap defaults site defaults]])
; 禁用CSRF进行测试
(def应用程序
(->路径处理程序
(包装默认值(关联站点默认值:安全性假)))
现在您可以在测试中使用此应用程序
(ns users.views-test)
(:需要[utilities.testing:参考[app]]
;...
))
;...
(测试“身份证张贴路线”
(let[response(app(mock/request:post)/“{:id“Foo”}”)]
(是(=302(:状态响应(()))))