3

背景

我是 Clojure 的新手,所以请原谅任何明显的错误。我正在尝试测试一些使用redis-clojure库的 Clojure 数据访问代码。虽然我的集成测试当然会测试整个堆栈,但我不希望我的单元测试依赖于连接到 redis 服务器实例。使用Midje 模拟实际的 Redis 命令似乎相对简单,但是,连接宏更难处理。

需要的建议

通过Midje文档似乎无法做或找不到的是模拟redis 连接或重新定义宏的方式。core.clj中相关的顶级连接宏是:

(defmacro with-server
  "Evaluates body in the context of a connection to Redis server
  specified by server-spec.

  server-spec is a map with any of the following keys:
    :host     (\"127.0.0.1\")
    :port     (6379)
    :db       (0)
    :timeout  (5000)
    :password (nil)"
  ([server-spec & body]
     `(with-connection connection# *pool* ~server-spec
        (binding [redis.vars/*channel* (make-direct-channel connection#)]
          ~@body))))

这里的上下文中的原始代码

我似乎无法在我的测试代码中重新定义宏,并且将宏包装在一个函数中不会让我进一步前进,因为我仍然需要执行主体来产生我的结果。我最想做的是执行传递给连接宏的主体并丢弃宏的其余部分。有任何想法吗?

4

2 回答 2

2

我经常编写绑定包装宏进行测试。这些宏只是将其他东西绑定到无法测试的函数或宏。在这种情况下,我会按照这些思路写一些东西

(defmacro my-fake-with-server []
   ....)

(defmacro with-fake-with-server
      (binding [redis.core/with-server my-fake-with-server]
               (insert test here)))

(deftest my-test (with-fake-with-server (function-that-uses-with-server)))

这会在您的测试代码中保留所有模拟。

于 2012-04-30T23:50:59.157 回答
1

我建议在Midje 邮件列表上提出您的问题(当然,然后在这里发布最终答案)。在不知道您要测试什么的情况下,很难给出建议。也许(在 Freeman 和 Pryce 的不断发展的面向对象软件之后(这确实适用于 Clojure - 实际上,支持这种风格是我编写 Midje 的原因)),您想将您的问题分成两部分。首先,您要构建一组隔离 Redis 的函数。您可以通过与真实数据库一起使用的缓慢而繁琐的直接测试来测试这些功能是否正常工作。

这些函数将隐藏连接和对包装宏的需求。

然后,您可以使用 Midje 先决条件测试您的代码是否正确调用了隔离函数。

Avdi Grimm 的Objects on Rails是另一本书,在讨论隔离数据库方面做得不错。

注意:我对 Redis 一无所知,但其他几个 Clojure-> 数据库库省略了具有智能吸引力的包装宏 ( with-server)。相反,它们走有状态的路线并有一个保存连接的全局变量,就像(比如说)Ruby 数据库库 ActiveRecord(隐式)和 Sequel(显式)所做的那样。尽管不那么纯粹,但它似乎让生活(包括测试)变得更简单。在 Midje 中,这种联系可以用元常数来表示。

于 2012-05-10T00:49:49.193 回答