在Clojure测试中存根HTTP请求的策略

时间:2017-03-01 15:48:53

标签: clojure mocking stubbing

我想知道是否有一种广泛使用的模式或解决方案,用于在Clojure集成测试中将出站HTTP请求存根到第三方(Ruby的webmock)。我希望能够在高级别(例如,在设置函数中)存储请求,而不必将我的每个测试包装在(with-fake-http [] ...)之类的内容中,或者不得不求助于依赖注入。 / p>

对于动态变量,这是一个很好的用例吗?我想我可以在设置步骤中进入有问题的命名空间,并将副作用函数设置为无害的匿名函数。然而,这感觉很苛刻,我不喜欢改变我的应用程序代码以适应我的测试的想法。 (它也不比上面提到的解决方案好很多。)

交换包含假函数的特定于测试的ns是否有意义?在我的测试中是否有一种干净的方法可以做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以使用ring / compojure框架看到一个很好的示例:

> lein new compojure sample
> cat  sample/test/sample/handler_test.clj


(ns sample.handler-test
  (:require [clojure.test :refer :all]
            [ring.mock.request :as mock]
            [sample.handler :refer :all]))

(deftest test-app
  (testing "main route"
    (let [response (app (mock/request :get "/"))]
      (is (= (:status response) 200))
      (is (= (:body response) "Hello World"))))

  (testing "not-found route"
    (let [response (app (mock/request :get "/invalid"))]
      (is (= (:status response) 404)))))

更新

对于出站http呼叫,您可能会发现with-redefs有用:

(ns http)

(defn post [url]
  {:body "Hello world"})

(ns app
  (:require [clojure.test :refer [deftest is run-tests]]))

(deftest is-a-macro
  (with-redefs [http/post (fn [url] {:body "Goodbye world"})]
    (is (= {:body "Goodbye world"} (http/post "http://service.com/greet")))))

(run-tests) ;; test is passing

在此示例中,原始函数post返回" Hello world"。在单元测试中,我们使用存根函数暂时覆盖post,返回" Goodbye world"。

完整文档is at ClojureDocs

答案 1 :(得分:1)

我曾经遇到类似的情况,我无法找到满足我需求的任何Clojure库,因此我创建了自己的库Stub HTTP。用法示例:

(ns stub-http.example1
  (:require [clojure.test :refer :all]
            [stub-http.core :refer :all]
            [cheshire.core :as json]
            [clj-http.lite.client :as client]))

(deftest Example1  
    (with-routes!
      {"/something" {:status 200 :content-type "application/json"
                     :body   (json/generate-string {:hello "world"})}}
      (let [response (client/get (str uri "/something"))
            json-response (json/parse-string (:body response) true)]
        (is (= "world" (:hello json-response))))))