使用 Clojure + Midje 重新定义宏操作



Background

我是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))))

(此处上下文中的原始代码(

似乎无法在我的测试代码中重新定义宏,并且将宏包装在函数中并不能让我进一步前进,因为我仍然需要执行主体来生成我的结果。理想情况下,我想做的是执行传递到连接宏中的主体并丢弃宏的其余部分。有什么想法吗?

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

(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)))

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

我建议在Midje邮件列表中提出您的问题(然后,当然,在这里发布最终答案(。不知道您要测试的内容,就很难提供建议。也许(遵循Freeman和Pryce的Growing Object-Oriented Software(它确实适用于Clojure - 事实上,支持这种风格是我写Midje的原因((,你想把你的问题分成两部分。首先,您需要构建一组隔离 Redis 的函数。您可以通过适用于实际数据库的缓慢而繁琐的直接测试来测试这些函数是否正常工作。

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

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

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

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

最新更新