This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-10
Channels
- # announcements (1)
- # babashka (18)
- # beginners (122)
- # calva (18)
- # cider (3)
- # cljs-dev (2)
- # cljsrn (3)
- # clojure (102)
- # clojure-europe (15)
- # clojure-france (2)
- # clojure-nl (1)
- # clojure-portugal (1)
- # clojure-spec (3)
- # clojure-uk (8)
- # clojurescript (46)
- # clojureverse-ops (5)
- # code-reviews (1)
- # conjure (2)
- # cursive (15)
- # datalog (13)
- # datomic (18)
- # emacs (4)
- # fulcro (8)
- # helix (8)
- # instaparse (1)
- # introduce-yourself (2)
- # jobs (4)
- # leiningen (23)
- # lsp (26)
- # malli (21)
- # off-topic (34)
- # pedestal (21)
- # polylith (6)
- # reitit (5)
- # remote-jobs (3)
- # schema (1)
- # sci (8)
- # shadow-cljs (8)
- # spacemacs (3)
- # sql (30)
- # testing (31)
- # tools-deps (21)
- # vim (25)
- # xtdb (8)
is there any good method for mocking something like java.util.Date.
? I am creating a map with a :date
entry and don’t want to have to worry about what it actually is when testing against the other contents
i know i could write (map #(dissoc % :date))
in my test but that’s so cumbersome, especially when writing multiple tests
i’d prefer to just write (= [{:date nil :text "Hello!"}] (-> (sut/new-game) (sut/add-message "Hello!") (:messages)))
i just had the thought that a simple (defn new-date [] (java.util.Date.))
allows me to use with-redefs
, but is that doesn’t seem generalizable. It will work for now so I’m not going to spend more time on this, but i’m still curious
if your code depends on the clock, then you should consider giving it a now
parameter
lol, side-cause is a great name
interesting. so how do i pass it in? i hope to allow the engine (for a game) to add messages from anywhere, which makes me think it’ll be cumbersome to have to call (java.util.Date.)
every time I want to add a message
once I’ve done it a couple times i start thinking “okay, how do I refactor to remove duplication?”
you could have a little message constructor that captures the clock
(defn messasge [m] {:msg m :time (java.util.Date)})
wow, I'm completely incapable of typing today
so I would call (add-message game (message "Hello!"))
in the engine instead of (add-message game "Hello!")
? and in a test I can just pass in (sut/add-message game {:date nil :text "Hello!"})
?
sure, that's reasonable
seems like all i’ve done is move the (java.util.Date.)
from within add-message
to message
. maybe I don’t understand enough, or maybe I haven’t done a good enough job of showing my code up front lol
classic X/Y problem
(defn add-message [game message]
(update game :messages conj {:date (java.util.Date.)
:text message}))
what are you trying to do by putting a nil in for the date?
allow me to test against the whole :messages
vector without having to deliberately exclude the :date
key in my equality checks
Hey @UEENNMX0T - sorry for resurrecting a week-old thread, but I think this is some real insight that may have been overlooked. > allow me to test against the whole `:messages` vector without having to deliberately exclude the `:date` key in my equality checks Irrespective of whether you want to have an external clock passed to functions (so you can test and easily control behavior based on time); if what you want to do is check equality without dates; then that is code that should exist somewhere directly in the test codebase:
(is (= expected-msgs (elide-dates generated-msgs)))
How you implement eldie-dates
is up to you; it could be as simple as a helper function that does dissoc
on each message in the collection, or it could use some fancy testing matching library (ala https://github.com/nubank/matcher-combinators) or some fancy data wrangling library (ala https://github.com/noprompt/meander or https://github.com/redplanetlabs/specter) or some fancy query library (ala https://github.com/lilactown/autonormal)ha I wrote get-messages
which does what your elide-dates
does: (defn get-messages [game] (mapv #(dissoc % :date) (:messages game)))
. Glad to know i’m not too far off
This is an alternative which actually mocks "creating a date", whether it is better or worse 🤷
(defn now []
(java.util.Date.))
(def freezed-time #inst "2022-03-09T15:54:02.699-00:00")
(with-redefs [now (constantly freezed-time)]
(= (now) #inst "2022-03-09T15:54:02.699-00:00")) => true
That’s a good one too!
If you ever start using the "newer" (immutable) dates in Java:
https://github.com/dm3/clojure.java-time
They have a built-in with-clock
that can help you mock time in tests:
(with-clock (system-clock "UTC")
(zoned-date-time 2015 10))
=> #<java.time.ZonedDateTime 2015-10-01T00:00Z[UTC]>
Another possibility, which I kind of hesitate to mention: if two messages are logically equal even if the dates are different, then perhaps the date should be metadata.
but it sounds like that's not the case, instead it's just for the test assertion.
defn add-message [game message {:keys [date] :or {:date (Date.)}}]
poor man's DI / Functional Architectureoh! that’s clever