Clojure数据库单元测试/模拟

13

我最近开始处理一个数据库密集型的Clojure应用程序,并试图设置一些单元测试。理想情况下,我希望通过模拟来避免实际访问真实数据库。

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

test-core.clj

(deftest core-test
  (is (> (count (fn-under-test "foo")) 0)))

core.clj

(defn fn-under-test [slug]
  (db/query "select * from %1" slug))

db.clj

(defn query [q & args]
  (sql/with-connection db
    (sql/with-query-results res
      [(clause q args)]
      (doall res))))

我的问题是:是否可以在test-core.clj内部绑定自定义函数到'db/query',以便core.clj使用它,而不是在db.clj中定义的内容?
谢谢!
1个回答

12
你可以使用binding来尝试覆盖db/query,但你需要先定义命名空间和变量。最简单的方法是将db.clj导入到相同的命名空间中,然后使用bindings。
(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))))

谢谢!今天早些时候我尝试使用binding(和with-binding),但是无法成功 - 我一直收到“主线程中的异常:java.lang.Exception:无法在此上下文中解析变量:db/query”的错误提示。 - eff
你可以尝试在测试中引用db.clj,然后使用bindings。 - Jeff
3
注意:自Clojure 1.3起,binding 只有在变量被声明为具有动态元数据时才能工作。使用with-redefs代替可以避免这个问题。 - Ming

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接