Clojure数据库单元测试/模拟

eff*_*eff 12 database testing clojure mocking

我刚刚开始研究数据库密集的Clojure应用程序,并尝试进行一些单元测试.理想情况下,我想通过嘲笑事实来避免实际打到真正的数据库.

这是一个简单测试的例子:

测试core.clj

(deftest core-test
  (is (> (count (fn-under-test "foo")) 0)))
Run Code Online (Sandbox Code Playgroud)

core.clj

(defn fn-under-test [slug]
  (db/query "select * from %1" slug))
Run Code Online (Sandbox Code Playgroud)

db.clj

(defn query [q & args]
  (sql/with-connection db
    (sql/with-query-results res
      [(clause q args)]
      (doall res))))
Run Code Online (Sandbox Code Playgroud)

我的问题:有没有办法从test-core.clj中将自定义函数绑定到'db/query',这样core.clj就会使用它,而不是db.clj中的定义?

谢谢!

Jef*_*eff 11

您可以使用绑定来尝试覆盖db/query,但是您需要首先定义命名空间和var.最简单的方法是将db.clj导入到同一名称空间中,然后使用绑定.

(ns test-core
    (:use clojure.test)
    (:require db))

(deftest core-test
  (binding [db/query (fn [query & args] (comment return some value here))]
    (is (> (count (fn-under-test "foo")) 0))))
Run Code Online (Sandbox Code Playgroud)

  • 注意:从Clojure 1.3开始,只有在使用动态元数据声明var的情况下,绑定才能起作用。使用`with-redefs`可以避免这个问题。 (2认同)