feychu
feychu

Reputation: 1364

Testing map with timestamp value in Clojure

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

Answers (3)

Luiz França
Luiz França

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

Arthur Ulfeldt
Arthur Ulfeldt

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

pete23
pete23

Reputation: 2280

Either remove the timestamp, or provide a way of making (current-timestamp) produce a known value rather than clock time.

Upvotes: 0

Related Questions