Reputation: 12983
I am trying to write a test like this:
(deftest login-form-rendering
(async done (with-redefs [http/post fake-login-success]
(with-mounted-component (c/login-form login!)
(fn [c div]
(.click (.getElementById js/document "Login"))
(is (= (:page @app-state) :location)))))
(done)))
I have this mock:
(defn fake-login-success [& _]
(let [ch (chan)
response {:status 200}]
(go (>! ch response)
ch)))
The login function does this:
(defn login! [username password]
(go (let [result (->> {:form-params {:username @username :password @password}}
(http/post "/api/login")
(<!))
{status :status body :body} result]
(case status
401 (swap! app-state assoc :page :bad-login)
200 (swap! app-state assoc :page :location)))))
The login form is a reagent component that takes a callback for onClick. app-state is a globally accessible atom.
The problem I'm facing is that the go block inside login! is never executed. Is there something I need to do to flush the channel or something?
I see there is also this unanswered question that's similar: Testing core.async code in ClojureScript. One difference seems to be that I don't have an explicit channel in my code under test. That's being generated by the cljs-http post.
Upvotes: 2
Views: 434
Reputation: 3014
I believe your problem is a misplaced parenthesis.
(let [ch (chan)
response {:status 200}]
(go (>! ch response)
ch))
The return value of this let
is the go
block's channel. It is a channel containing nothing, since:
go
block is trying to put on an unbuffered channel, requiring some other operation to "meet" it and do the complementary take in order for its own execution to proceed. ch
is lexically hidden from the outside world, so no operation can exist which can perform the complementary take. If something somehow did take from it (or we added a buffer to ch
so the first put succeeds), ch
would be put on the returned channel.
(let [ch (chan)
response {:status 200}]
(go (>! ch response))
ch)
The return value of this let
is ch
, with no additional channel wrapping it. The go
-block is parked trying to put on ch
until something like your test gets around to taking from it.
However, since we're ultimately just looking to construct a channel with a constant on it, go
itself seems like the simplest solution:
(defn fake-login-success [& _]
(go {:status 200})
Upvotes: 4