What substitutions are for

In the tests of your application, or when developing it, you may want to mock the lifecycle expressions of a defstate. This way, the global state will result in another value when started.

Setting substitutions for (start)

To substitute a state, the call to the start function must be wrapped by the with-substitutes macro. A substitute is not defined with defstate, but with the state macro. For example:

(mount/with-substitutes [#'db (state :start (do (println "Starting fake DB") (atom {}))
                                     :stop  (println "Stopping fake DB"))]
;>> Starting fake DB
;=> (#'

;=> object[clojure.lang.Atom 0x2010a30b {:status :ready, :val {}}]

;>> Stopping fake DB
;=> (#' #'

A substitution is only active for the current session. Thus, starting the state again (after is has been stopped), without a substitute configured for it, will start it with the original definition.

Note that substitution states don’t need to be inline. And the with-substitutes wrappers can be nested. For example, the following is also possible:

(def sub (state :start {}))

(mount/with-substitutes [#'db sub]
  (mount/with-substitutes [#'config sub]