如何避免在Clojure中进行单元测试时手动评估defrecords和defprotocols?

时间:2013-01-16 16:36:08

标签: clojure

在我的Clojure代码库中,我定义了几个协议和几个defrecords。我正在使用clojure.test对我的defrecords中定义的具体函数进行单元测试。

例如,假设我有以下源文件:

在src / foo / protocols.clj中:

(ns foo.protocols)

(defprotocol RequestAcceptability
  (desired-accepted-charset [this]))

在src / foo / types.clj中:

(ns foo.types
  (:use [foo.protocols :only [RequestAcceptability desired-accepted-charset]])

(defrecord RequestProcessor
  [field-1 field-2]
  RequestAcceptability
  (desired-accepted-charset [this]
    ...implementation here...))

在test / foo / types_test.clj中:

(ns foo.types-test
  (:use [clojure.test])
  (:use [foo.protocols :only [RequestAcceptability desired-accepted-charset]])
  (:import [foo.types RequestProcessor]))

(deftest test-desired-accepted-charset_1
  ...test code here...)

我在Emacs中使用Clojure 1.4,Leiningen 2,nrepl。

我面临的烦恼是,当我去运行单元测试时(例如,使用C-c C-,序列),我得到一个 ClassNotFoundException:foo.types.RequestProcessor 。为了解决这个问题,我正在进行单独评估每个协议和defrecord表单的手动工作。即,我将导航到我的protocols.clj并评估(nrepl的C-M-x键序列)我的defprotocol形式;然后我将导航到我的types.clj并评估我的defrecord表单;然后我终于能够成功地运行我的单元测试而没有得到ClassNotFoundException。

当然,在我真正的代码库中,我必须为我的所有协议和defrecords执行此操作,因此这非常繁琐且耗时。另外,如果我只是简单地转到shell并执行 lein test ,我会得到相同的ClassNotFoundException。

有更好的方法吗?

感谢您的时间和帮助。

2 个答案:

答案 0 :(得分:4)

您需要require包含测试命名空间中的defrecord的命名空间。

(:import [foo.types RequestProcessor]))不会单独工作,因为它只适用于类路径中已存在的Java类。这不是这种情况,因为您正在使用defrecord在运行时动态创建类。

通常只有Java互操作才需要

import

答案 1 :(得分:2)

动态defrecord 在运行时生成类。一旦你进入命名空间并运行代码,那么这个类就会出现并且测试会正常加载,因为这个类现在已经存在了。如果use除了import类之外,测试中的命名空间是否为您正确加载?