如何与redefs一起使用来模拟对同一函数的多个调用



我希望能够模拟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)))))

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

(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)))]
...)

我们使用Picomock来实现这一点,并对每个调用的参数进行断言,并对调用次数进行断言。推荐!

最新更新