【问题标题】:How can I use with-redefs to mock multiple calls to the same function?如何使用 with-redefs 模拟对同一函数的多个调用?
【发布时间】:2019-04-02 15:40:42
【问题描述】:

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

【问题讨论】:

    标签: unit-testing clojure mocking compojure


    【解决方案1】:

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

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

    【讨论】:

    • 我收到Unable to resolve symbol: swap-vals! in this context
    • @Freid001 swap-vals! 是在 Clojure 1.9 中引入的,因此您必须使用之前的版本。我更新了另一个不使用swap-vals!的示例。
    【解决方案2】:

    为此,我们使用 Picomock,并对每个调用的参数进行断言,并对调用次数进行断言。推荐!

    【讨论】:

      猜你喜欢
      • 2019-04-18
      • 1970-01-01
      • 2019-11-05
      • 2020-07-15
      • 1970-01-01
      • 2022-11-02
      • 2022-01-26
      • 2017-09-07
      • 1970-01-01
      相关资源
      最近更新 更多