How to avoid having to manually evaluate defrecords and defprotocols while unit testing in Clojure?

▼魔方 西西 提交于 2019-12-23 11:13:50

问题


In my Clojure codebase, I have defined several protocols and several defrecords. I am using clojure.test to unit test the concrete functions defined within my defrecords.

For example, let's say I have the following source files:

In src/foo/protocols.clj:

(ns foo.protocols)

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

In 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...))

In 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...)

I am using Clojure 1.4, Leiningen 2, nrepl within Emacs.

The annoyance I am facing is that when I go to run my unit tests (e.g., using C-c C-, sequence), I get a ClassNotFoundException: foo.types.RequestProcessor. To get around this, I'm doing the manual work of evaluating, individually, each of my protocol and defrecord forms. I.e., I'll navigate over to my protocols.clj and evaluate (C-M-x key sequence for nrepl) my defprotocol form; and then I'll navigate to my types.clj and evaluate my defrecord form; and then finally I'm able to successfully run my unit tests w/out getting the ClassNotFoundException.

Of course, in my real code base, I have to do this for all my protocols and defrecords, and so it is very tedious and time consuming. Also, if I simply drop to a shell and do lein test, I get the same ClassNotFoundException.

Is there a better way?

Thank you for your time and help.


回答1:


You need to require the namespace that contains the defrecord in your test namespace.

(:import [foo.types RequestProcessor])) won't work on its own, since that only works for Java classes that already exist on the classpath. This isn't the case here, since you are using defrecord to dynamically create the class at runtime.

import is usually only needed for Java interop.




回答2:


defrecord dynamically generates the class when it is run. Once you go into the namespace and run the code, then the class comes into being and the tests load normally because the class now exists. If you use the namespace from within your tests in addition to importing the class does it load properly for you?



来源:https://stackoverflow.com/questions/14363216/how-to-avoid-having-to-manually-evaluate-defrecords-and-defprotocols-while-unit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!