如何使用with-redefs模拟对同一函数的多次调用?

时间:2018-10-29 16:37:27

标签: unit-testing clojure mocking compojure

我希望能够模拟MyFunction,但是当调用MyFunction时我需要模拟返回不同的值。

是否可以根据功能的调用顺序使用with-redefs返回不同的值?

(testing "POST /foo/bar and return ok"
  (with-redefs [->Baz (fn [_]
                    (reify MyProtocol (MyFunction [_] [{:something 1}]))
                    (reify MyProtocol (MyFunction [_] [{:something 2}])))]

    (let [response (routes/foo {:request-method :post
                            :uri            "/foo/bar"
                            :query-params   {}
                            })]

      (is (= (:status response) 200)))))

2 个答案:

答案 0 :(得分:5)

您可以使用可变的返回值集合,然后在每次调用时从中返回/删除值。

(defn foo [x] (inc x)) ;; example fn to be mocked

如果您要模拟对foo的三个调用,分别返回1、2和3:

(with-redefs [foo (let [results (atom [1 2 3])]
                    (fn [_] (ffirst (swap-vals! results rest))))]
  (prn (foo 0))
  (prn (foo 0))
  (prn (foo 0))
  ;; additional calls would return nil
  (prn (foo 0)))
;; 1
;; 2
;; 3
;; nil

使用swap-vals!获取原子的旧值/新值,但需要Clojure 1.9或更高版本。

如果您没有swap-vals!,则可以这样做(原子程度较低),如下所示:

(with-redefs [foo (let [results (atom [1 2 3])]
                    (fn [_]
                      (let [result (first @results)]
                        (swap! results rest)
                        result)))]
  ...)

答案 1 :(得分:1)

为此,我们使用Picomock,并为每个调用确定参数,并确定调用次数。推荐!