Reputation: 1364
I am testing a function in Clojure which takes a map as input and outputs a map to which the field :timestamp (current-timestamp)
is added.
I have problems testing for equality as I cannot predict which timestamp will be added by the function.
(is (= output (convert-map input)))
I thought about dissoc
-ing the :timestamp
from the output of the function but that seems convoluted, so I wonder if there is a better solution.
Upvotes: 1
Views: 458
Reputation: 106
You could use the fn with-redefs
, and make the fn you're using to get the timestamp always return the same timestamp when testing.
(with-redefs [timestamp-fn (constantly "2019-07-28T12:00:00Z")]
(your-fn params))
You can read about it here: https://clojuredocs.org/clojure.core/with-redefs
Upvotes: 3
Reputation: 91577
Clojure's metadata feature was designed with this in mind. It provides a way to store information about some data that is independent of the data itself.
user> (defn convert-map [input]
(with-meta input {:timestamp (clj-time.core/now)}))
#'user/convert-map
user> (convert-map {:a 1 :b 1})
{:a 1, :b 1}
user> (def input {:a 1 :b 1})
#'user/input
user> (def output (convert-map {:a 1 :b 1}))
#'user/output
user> (:timestamp (meta output))
#object[org.joda.time.DateTime 0x29eb7744 "2019-07-25T15:36:16.609Z"]
user> (= input output)
true
This preserves all equality concepts. It is very useful to keep in mind that the metadata is attached to a particular data so if you do something that copies the contents from input into some other data structure then this metadata would not come along as in this example:
user> (meta (merge output {:c 0}))
{:timestamp
#object[org.joda.time.DateTime 0x29eb7744 "2019-07-25T15:36:16.609Z"]}
user> (meta (merge {:c 0} output))
nil
Upvotes: 1
Reputation: 2280
Either remove the timestamp, or provide a way of making (current-timestamp) produce a known value rather than clock time.
Upvotes: 0