我试图为我的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.
你已经有一个与工作功能版本不远的地方.我改变了一些事情,对Clojure更为惯用.
以下假设生成天空节点和生成热节点每个都返回一些值(除了它们具有的任何副作用之外,这可以完成),即:
- (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)))))
一般的想法是,你不测试它做了什么,你测试它返回什么.然后你安排你的代码,以便(尽可能的话)关于一个函数调用的一切都是它返回的.
另外一个建议是通过使用生成天空节点和生成热节点来最大限度地减少发生副作用的地方,以返回要执行的副作用:
- (defn generate-sky-nodes
- []
- (fn []
- (doseq [i (range 10)] (do-make-sky-node i))
- :sky-nodes))
- (apply (generate-nodes blue-test hot-test name) [])
或更简洁(尽管如果您不熟悉Clojure,诚然奇怪):
- ((generate-nodes blue-test hot-test name))