Как я могу использовать with-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)))))
2 ответа
Вы можете использовать изменяемую коллекцию возвращаемых значений, а затем возвращать / удалять значения из нее при каждом вызове.
(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, чтобы утверждать параметры для каждого вызова и утверждать количество вызовов. Рекомендуемые!