I am using Timbre as a logging library but I am having issues testing it with Midje . I've got the following method and all I'm trying to do is asserting that Will be printed
is 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"))
By wrapping (timbre/default-output-fn)
around a function of my own my-output-fn
, I am able to assert that only 1 out of 2 logs are printed, which is true:
(fact "print info but not debug"
(core/init :info) => nil
(provided
(core/my-output-fn anything) => irrelevant :times 1))
However I would like to make sure that the message being printed is Will be printed
. I can't find any way of doing this, what would you do?
I am doing experiments in the following project https://github.com/stephanebruckert/timbre-midje
It is possible to validate the input of a function using Midje's as-checker
prerequisite .
When you print the data
that come into timbre/default-output-fn
(I discovered this via your output-fn
) you see it has the following structure:
{:hash_ #delay[{:status :pending, :val nil} 0x5ed805b1], :instant #inst "2016-10-14T17:07:16.779-00:00", :config {:level :info, ....
So the log-level is available in data
. With as-checker
the log level
can be validated as follows:
(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))
Now, you wanted to check the content of the message. Not only the log level.
The actual message is not available in the opts
or data
passed toward default-output-fn
. Looking around in the the Timbre code I saw it is available in a private function vargs->margs
that takes an ?err
, a msg-type
and vargs
. The vargs
contain the message (in your case what comes in is for example :auto :p ["The message"])
.
Via the as-checker
approach the messages can be validated follows:
(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) )
Note that vargs->margs
has to return a map, otherwise Timbre throws an exception in a later function.
This way it is validated that "Will be printed" is printed once, and "Won't be printed" is never printed.
@ErwinRooijakkers' idea worked but @ptaoussanis on Github has a good reason not to do it.
Please note that
timbre/vargs->margs
is private, and an implementation detail. Its behaviour can change at any time without notice, would strongly recommend not depending on it in any way.It'd be possible to use a custom appender that sends output somewhere that are handy for your tests to analyse. You could setup these appenders as part of your test setup, and/or use something like
timbre/with-config
for the appropriate test calls.
So we can add an appender that passes the parameters to check ( level
message
) to a stub.
core.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))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.