2

我将Timbre用作日志库,但在使用Midje测试它时遇到问题。我有以下方法,我要做的就是断言Will be printed已打印。

(defn init [level]
    (timbre/merge-config! {:output-fn my-output-fn})
    (timbre/set-level! level)
    (timbre/info "Will be printed")
    (timbre/debug "Won't be printed"))

通过包装(timbre/default-output-fn)我自己的函数,my-output-fn我可以断言只有 2 个日志中的 1 个被打印,这是真的:

(fact "print info but not debug"
    (core/init :info) => nil
    (provided
        (core/my-output-fn anything) => irrelevant :times 1))

但是,我想确保正在打印的消息是Will be printed. 我找不到任何方法可以做到这一点,你会怎么做?

我正在以下项目中进行实验https://github.com/stephanebruckert/timbre-midje

4

2 回答 2

3

可以使用 Midje 的as-checker先决条件来验证函数的输入。

当您打印data进入的timbre/default-output-fn(我通过您的 发现这个output-fn)时,您会看到它具有以下结构:

{:hash_ #delay[{:status :pending, :val nil} 0x5ed805b1], :instant #inst "2016-10-14T17:07:16.779-00:00", :config {:level :info, ... .

所以日志级别在data. 可以验证as-checker如下log level

(fact "print info but not debug"
      (core/init :info) => nil
      (provided
       (timbre/default-output-fn anything ; opts is first argument
                                 (as-checker (fn [data]
                                               (= (-> data :config :level) ; get log level
                                                  :info))))     ; validate that it is info
       => anything :times 1)
      (provided
       (timbre/default-output-fn anything
                                 (as-checker (fn [data]
                                               (= (-> data :config :level)
                                                  :debug))))
       => anything :times 0))

现在,您想检查消息的内容。不仅是日志级别。

opts实际消息在或data传递给 中不可用default-output-fn。在 Timbre 代码中环顾四周,我看到它在一个私有函数vargs->margs中可用,该函数需要一个?err, amsg-typevargs. vargs包含消息(在您的情况下,例如:auto :p ["The message"]).

通过该as-checker方法,可以验证消息如下:

(fact "print Will be printed, not Won't be printed"
      (core/init :info) => nil
      (provided
       (#'timbre/vargs->margs anything anything ["Will be printed"]) => {} :times 1)
      (provided
       (#'timbre/vargs->margs anything anything ["Won't be printed"]) => {} :times 0) )

注意vargs->margs必须返回一个映射,否则 Timbre 会在后面的函数中抛出异常。

这样可以验证“将被打印”打印一次,而“不会被打印”永远不会打印。

于 2016-10-14T17:58:17.820 回答
2

@ErwinRooijakkers 的想法奏效了,但Github 上的 @ptaoussanis有充分的理由不这样做。

请注意,这timbre/vargs->margs是私有的,并且是实现细节。它的行为可以随时更改,恕不另行通知,强烈建议不要以任何方式依赖它。

可以使用自定义附加程序将输出发送到方便您的测试分析的地方。您可以将这些附加程序设置为测试设置的一部分,和/或使用类似的东西timbre/with-config进行适当的测试调用。

所以我们可以添加一个将参数传递给检查(level message)的附加程序到存根。

核心.clj

(defn init
  ([level]
    (init level {}))
  ([level config]
    (timbre/merge-config! config)
    (timbre/set-level! level)
    (timbre/info "will be printed")
    (timbre/debug "won't be printed")))

core_test.clj

(:require [timbre-midje.core :as core]
          [midje.sweet :refer :all]))

(defn log-stub [level message])

(def log-stub-appender
  {:appenders
    {:test-appender
      {:enabled? true
       :fn (fn [data] (log-stub (:level data) (:vargs data)))}}})

(fact "print info but not debug"
  (core/init :info log-stub-appender) => nil
  (provided
    (log-stub :info ["will be printed"]) => irrelevant :times 1
    (log-stub :debug ["won't be printed"]) => irrelevant :times 0))
于 2016-10-18T20:37:24.947 回答