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
you probably want something like: https://github.com/tolitius/mount/blob/master/test/core/mount/test/fun_with_values.cljc#L26
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
yep
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 everythingmount
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 deref
ing 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
?