mar*_*hon 2 macros unit-testing clojure
我想在命名空间中模拟一个宏.
例如,clojure.tools.logging/error.
我试着with-redefs没有运气
(def logged false)
(defmacro testerror
{:arglists '([message & more] [throwable message & more])}
[& args]
`(def logged true))
(deftest foo
...
(with-redefs
[log/error testerror]
...
Run Code Online (Sandbox Code Playgroud)
这给了这个错误:
CompilerException java.lang.RuntimeException: Can't take value of a macro
你不能做这个.宏的重点在于,在编译代码时它们会被扩展,之后它们就会消失.包含对宏的调用的原始代码是不可恢复的.您无法在运行时追溯重新定义宏:您已经太晚了.
如果您希望具有可交换日志记录实现,另一种方法是使用Component之类的内容来进行依赖项注入,并根据您是运行测试还是运行实际程序来使用不同的日志记录组件.可以说这有点笨拙,也许有一种更简单的方法,但我不知道.
Amalloy 为您提供了有关如何模拟宏的直接问题的答案 - 您不能。
但是,您可以使用其他解决方案来解决您的问题(比将整个应用程序移至组件依赖项注入更简单)。让我建议两种替代实现(不幸的是,不是很简单,但仍然比使用组件更简单)。
您不能模拟宏,但可以模拟扩展日志记录宏时将使用的函数。
(require '[clojure.tools.logging :as log])
(require '[clojure.pprint :refer [pprint]])
(pprint (macroexpand `(log/error (Exception. "Boom") "There was a failure")))
Run Code Online (Sandbox Code Playgroud)
给出:
(let*
[logger__739__auto__
(clojure.tools.logging.impl/get-logger
clojure.tools.logging/*logger-factory*
#object[clojure.lang.Namespace 0x2c50fafc "boot.user"])]
(if
(clojure.tools.logging.impl/enabled? logger__739__auto__ :error)
(clojure.core/let
[x__740__auto__ (java.lang.Exception. "Boom")]
(if
(clojure.core/instance? java.lang.Throwable x__740__auto__)
(clojure.tools.logging/log*
logger__739__auto__
:error
x__740__auto__
(clojure.core/print-str "There was a failure"))
(clojure.tools.logging/log*
logger__739__auto__
:error
nil
(clojure.core/print-str x__740__auto__ "There was a failure"))))))
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,执行实际日志记录(如果启用了给定级别)的函数是通过clojure.tools.logging/log*函数完成的。
我们可以模拟它并编写我们的测试:
(require '[clojure.test :refer :all])
(def log-messages (atom []))
(defn log*-mock [logger level throwable message]
(swap! log-messages conj {:logger logger :level level :throwable throwable :message message}))
(with-redefs [clojure.tools.logging/log* log*-mock]
(let [ex (Exception. "Boom")]
(log/error ex "There was a failure")
(let [logged (first @log-messages)]
(is (= :error (:level logged)))
(is (= "There was a failure!" (:message logged)))
(is (= ex (:throwable logged))))))
Run Code Online (Sandbox Code Playgroud)
您的日志记录库 API 可能提供允许您插入测试以收集和断言日志记录事件的功能。例如,使用java.util.logging,您可以编写自己的Handler实现,该实现将收集所有记录的日志记录并将其添加到特定(或根)记录器。
| 归档时间: |
|
| 查看次数: |
735 次 |
| 最近记录: |