我正在尝试为我的clojure函数编写一些单元测试(我正在使用clojure.test,但如果需要,我可以切换到midje。)
我的功能如下:
(defn GenerateNodes
[is-sky-blue? hot-outside? name]
(cond
(is-sky-blue? name) (generate-sky-nodes)
(hot-outside?) (generate-hot-nodes)))
单元测试此函数时,我想编写以下测试用例:
(deftest when-sky-blue-then-generate-sky-nodes
(let [is-sky-blue true]
(GenerateNodes (fn[x] println "sky nodes generated."))
(is (= true Was-generate-hot-nodes-called?))
如何断言函数generate-sky-nodes被调用?或不 ? 我会在C#或java中使用一个模拟框架,但我不知道clojure。
答案 0 :(得分:10)
你已经离功能版本不远了。我改变了一些东西,对Clojure更加惯用。
以下假设generate-sky-nodes和generate-hot-nodes都返回一些值(除了它们有任何副作用外,还可以这样做),即:
(defn generate-sky-nodes
[]
(doseq [i (range 10)] (do-make-sky-node i))
:sky-nodes)
然后,您的生成节点调整如下:
(defn generate-nodes
[sky-blue? hot-outside? name]
(cond
(sky-blue? name) (generate-sky-nodes)
(hot-outside?) (generate-hot-nodes)))
最后,测试的功能版本:
(deftest when-sky-blue-then-generate-sky-nodes
(let [truthy (constantly true)
falsey (constantly false)
name nil]
(is (= (generate-nodes truthy falsey name)
:sky-nodes))
(is (= (generate-nodes truthy truthy name)
:sky-nodes))
(is (not (= (generate-nodes falsey falsey name)
:sky-nodes)))
(is (not (= (generate-nodes falsey truthy name)
:sky-nodes)))))
一般的想法是你不测试它做了什么,你测试它返回什么。然后你安排你的代码,以便(只要有可能)所有关于函数调用的事情就是它返回的内容。
另一项建议是,使用generate-sky-nodes
和generate-hot-nodes
返回副作用,以尽量减少副作用发生的地方数量:
(defn generate-sky-nodes
[]
(fn []
(doseq [i (range 10)] (do-make-sky-node i))
:sky-nodes))
您对generate-nodes
的调用如下所示:
(apply (generate-nodes blue-test hot-test name) [])
或更简洁(尽管你对Clojure不太熟悉,但事实上很奇怪):
((generate-nodes blue-test hot-test name))
(在上述测试代码中作必要的修改,测试也适用于此版本)
答案 1 :(得分:9)
您可以自己编写宏来模拟函数并检查函数是否被调用。或者您可以使用expect-call库。
(defn check-error [a b]
(when (= a :bad-val)
(log :error b)))
; This will pass
(deftest check-logging
(with-expect-call (log [:error _])
(check-error :bad-val "abc")))
; This will fail
(deftest check-logging-2
(expect-call (log [:error _])
(check-error :good-val "abc")))
答案 2 :(得分:4)
使用Midje的checkables:
(unfinished is-sky-blue? hot-outside?)
(facts "about GenerateNodes"
(fact "when the sky is blue then sky nodes are generated"
(GenerateNodes is-sky-blue? hot-outside? ..name..) => ..sky-nodes..
(provided
(is-sky-blue? ..name..) => true
(generate-sky-nodes) => ..sky-nodes..
(generate-hot-nodes) => irrelevant :times 0)))
答案 3 :(得分:0)
您可以使用mock-clj。
(require ['mock-clj.core :as 'm])
(deftest when-sky-blue-then-generate-sky-nodes
(m/with-mock [is-sky-blue? true
generate-sky-nodes nil]
(GenerateNodes (fn[x] println "sky nodes generated.") ... ...)
(is (m/called? generate-sky-nodes))))