Тестирование с core.async - сбросить блоки внутри теста?

Я пытаюсь написать такой тест:

(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. app-state является глобально доступным атомом.

Проблема, с которой я сталкиваюсь, состоит в том, что блок go внутри входа в систему! никогда не выполняется. Есть ли что-то, что мне нужно сделать, чтобы очистить канал или что-то?

Я вижу, что есть также этот вопрос без ответа, который похож: Тестирование кода core.async в ClojureScript. Кажется, одно отличие состоит в том, что у меня нет явного канала в тестируемом коде. Это генерируется постом cljs-http.

1 ответ

Решение

Я считаю, что ваша проблема - неуместная скобка.

(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})
Другие вопросы по тегам