【问题标题】:Strategy for stubbing HTTP requests in Clojure tests在 Clojure 测试中存根 HTTP 请求的策略
【发布时间】:2017-03-01 15:48:52
【问题描述】:

我想知道在 Clojure 集成测试中是否有广泛使用的模式或解决方案来存根对第三方的出站 HTTP 请求(如 Ruby 的 webmock)。我希望能够在高级别(例如,在 setup 函数中)存根请求,而不必将我的每个测试都包装在 (with-fake-http [] ...) 之类的东西中,也不必求助于依赖注入。

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

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

【问题讨论】:

  • 大多数(全部?)clojure http 库将请求和响应表示为映射,因此您可以直接在测试中构建它们而无需模拟。
  • 依赖注入有什么问题?您是否在函数中硬编码网址?因为你不应该那样做,那很糟糕,mkay。

标签: clojure mocking stubbing


【解决方案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))))))

【讨论】:

  • 谢谢。我会调查你的图书馆并跟进。 :)
  • 有什么方法可以匹配路由中的/something/<all-uuid>
【解决方案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

完整文档is at ClojureDocs

【讨论】:

  • 谢谢。我已经更新了我的问题,以更具体地说明我试图存根的请求类型。具体来说,从我的应用程序到第三方的出站请求。
  • 再次感谢。我会尝试你的建议和跟进(可能需要几天)。乍一看,与 webmock 之类的解决方案相比,这相当笨拙,因为我需要深入了解嵌套函数调用将做什么。
猜你喜欢
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 2022-08-18
  • 2016-02-01
  • 2022-11-18
  • 2022-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多