unit-testing - Clojure 单元测试 : Check if a function was called

标签 unit-testing clojure mocking tdd midje

我正在尝试为我的 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 的习惯。

以下假设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-nodesgenerate-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))

(在上述测试代码中进行必要的修改后,测试也适用于此版本)

关于unit-testing - Clojure 单元测试 : Check if a function was called,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18328890/

相关文章:

clojure - 为什么 Clojure 的 for 宏只接受一个 body 表达式?

python - 有没有办法在模拟方法/函数中访问原始函数,以便我可以修改参数并将其传递给原始函数?

sqlite - 使用内存中的 sqlite DB 加速单元测试时避免 DB 依赖的建议

emacs - 使用 emacs+swank+slime+clojure 的良好工作流程?

clojure - 教堂数字的阶乘函数

java - 如何访问 Java 中的私有(private)类成员?

java - 使用 Bundle.class 抑制 TooManyMethodsFoundException

unit-testing - 我应该对 XML 模式进行单元测试吗?

c# - 如何模拟 SerialDataReceivedEventArgs

.net - 为什么要使用 Assert.ReplaceNullChars(string input)?