mount 2018-06-27

so an example of what I was talking about is the following. At the moment I have a state for the client.

(defstate ^{:doc "The Azure Blob Service instance

AZURE_STORAGE_CONNECTION_STRING will be used under the hood." }
  blob-service
  :start (az-storage/BlobService.))

and then a state for the fetch function

(defstate ^{:doc "A stateful function that fetches the schema files"}
  fetch-schema-fn
  :start do-fetch!)

would it be a good idea to drop the blob-service state? in any case I don't see myself mocking the javascript object directly

also at the point I would then need to surround each test with (-> (mount/only ..) (mount/swap-states ...))

if I understand correctly, I would do something like this:

(defstate ^{:doc "the azure connection" }
   az-conn
  :start (az/connect config))
(defstate schemas :start (fetch-schemas az-conn))

it is a personal preference, I try to narrow down state to primitives: i.e. connections, thread pools, queues, etc..

depending on how schemas are used it might not need to be a separate state

yep got it..the only difference in my case is that schemas is on-demand

so it has to be a function returning a function

ah ok, it's a "factory" (i.e. partial function)

yep...btw I am trying {:start #(fetch-schema-success! %)}

but it seems to trigger the call

maybe I am doing something wrong

where is it called from? i.e. why those places can't just call it as (fetch-schema-success! az-conn ...)?

the schema is parameterized by key at runtime

right, but you know the key at runtime

and you have a reference to az-conn, so why close over it?

well why not? I am never going to need to pass another conn

if i do at test time it is a mount state

but that is probably not going to happen

> well why not? I am never going to need to pass the another conn could be a personal preference: I usually minimize the number of stateful components

to keep functions "unaware"

yep I used to think the same and that is why I was having doubts

btw this works for me:

(-> (mount/only #{#'df-svc/fetch-schema-fn})
        (mount/swap-states {#'df-svc/fetch-schema-fn {:start (constantly fetch-schema-success!)}})
        (mount/start))
still torn about passing conn in to everything

mount makes it easy NOT to have that and still handle the swap/mock cleanly

definitely food for thought for me 😉

yea, this is all on you 🙂

I don't believe in the "ultimate truth"

another thing I have noticed in cljs apps

I have tests like the following

(testing "successfully fetching a definition schema - mocking the providers"

    (-> (mount/only #{#'df-svc/fetch-schema-fn})
        (mount/swap-states {#'df-svc/fetch-schema-fn {:start (constantly fetch-schema-success!)}})
        (mount/start))

    (let [event {:data #js {:amount 2.5 :method "cash"}
                 :key "42"
                 :entity "order"
                 :domain "salad-man"
                 :name "payment-added"}
          schema {:title "payment-added",
                  :description "Payment was taken for the order",
                  :properties {:method {:type "string"},
                               :amount {:type "number"}},
                  :required ["method" "amount"]}]
      (tu/async
        (-> (df-svc/fetch-schema! event)
            (.then #(is (= schema (js->clj % :keywordize-keys true)) "should return the right schema"))
            (.then #(mount/stop))))))

the last mount/stop kind of bothers me but I understand it is a necessary evil

a macro would solve that probably

does fetch-schema have a :stop function?

or you create az-conn in a :each / :once fixtures?

no I just ignore the connection in this test because I am replacing the caller

if the only thing that is started is {:start (constantly fetch-schema-success!)} "mount/stop" won't do anything since there are no stop functions

oh I thought I needed to call it anyways

only if you need to stop something 🙂

so derefing a state starts it implicitely...good to know 🙂

right, and you would call (mount/stop) to cleanup/destroy, but only when you have things to cleanup/destroy

@tolitius so I see a discrepancy that I do not understand:

(defstate fetch-schema-fn
  "A stateful function that fetches the schema files."
  :start do-provider-fetch!)
but in the tests I need
(-> (mount/only #{#'df-svc/fetch-schema-fn})
      (mount/swap-states {#'df-svc/fetch-schema-fn {:start (constantly fn)}}))

is there an additional eval going on for swap-states? just wanted to understand the difference...probably it has smth to do with the macro nature of defstate ?