使用core.async进行测试-在测试中清除go块



我正在尝试编写这样的测试:

(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)))

我有这个模拟:

(defn fake-login-success [& _]
  (let [ch (chan)
        response {:status 200}]
    (go (>! ch response)
        ch)))

登录功能是这样做的:

(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)))))

登录表单是一个对onClick进行回调的试剂组件。应用程序状态是一个全局可访问的原子。

我面临的问题是登录中的go阻塞!从不执行。我需要做些什么来冲洗通道吗?

我发现还有一个类似的未回答的问题:在ClojureScript中测试core.async代码。一个区别似乎是我在测试中的代码中没有明确的通道。这是由cljshttp帖子生成的。

我认为你的问题是放错了括号。

(let [ch (chan)
      response {:status 200}]
    (go (>! ch response)
        ch))

let的返回值是go块的信道。这是一个什么都不包含的通道,因为:

  1. go块正试图放置在一个无缓冲的通道上,需要一些其他操作来"满足"它并进行互补获取,以便继续执行它自己的操作
  2. ch在词汇上是对外界隐藏的,因此不可能存在可以执行互补获取的操作

如果某种东西确实从中拿走了(或者我们向ch添加了一个缓冲区,所以第一次放入成功),那么ch将被放入返回的通道中。

(let [ch (chan)
      response {:status 200}]
    (go (>! ch response))
    ch)

这个let的返回值是ch,没有额外的通道包装它。go-块停在那里,试图放在ch上,直到你的测试可以从中获取一些东西。

然而,由于我们最终只是想构建一个带有常量的通道,go本身似乎是最简单的解决方案:

(defn fake-login-success [& _]
  (go {:status 200})

最新更新