3

我仍处于 Cljs 和 Om 的学习阶段。我正在研究编写组件测试。一些组件cljs-http调用了我创建的 API。在测试时,我不希望这些 API 调用实际发送请求,所以我正在研究模拟请求并返回一个夹具。这是我拥有的示例组件:

(defn async-component [data owner]
  (reify
    IWillMount
    (will-mount [_]
      (let [resp (go ((<! (async-call "/") :body))]
        (om/update! data [:objects] resp)))
    IRender
    (render [_]
      [:ul
        (om/build-all item-component data)])))

(defn async-call [path]
  (http/get path {:keywordize-keys true}))

请不要介意代码实际上在语法上是否正确,我只是在展示它的要点。

我现在要做的是测试这个async-component和 API 调用,看看它是否会呈现我用来模拟请求的夹具。这是怎么做到的?我知道cljs.testasync测试异步代码的块,但所有示例都显示它测试只有 ago的实际代码块,而不是在更大的上下文中。

4

1 回答 1

5

这是您可以使用模拟来测试组件的一种方式:

(deftest test-async-component
  (cljs.test/async done
    (with-redefs
      [async-call (fn [path]
                    (let [mock-ch (async/chan 1)
                          fixture-data {:body {:fixture-with path :and "foobar"}})]
                      (async/put! mock-ch fixture-data)
                      mock-ch)]
      ; At this point we successfully mocked out our data source (the API call)
      ; the only task that remains is to render our Om component into DOM and inspect it.
      ; As this task requires utility fns I will reuse the ones in this blog post:
      ; http://lab.brightnorth.co.uk/2015/01/27/unit-and-browser-testing-om-clojurescript-applications/

      (let [c (new-container!)
            initial-data {:objects [{:initial-object 42}]}]
        ; This will mount and render your component into the DOM residing in c.
        (om/root async-component initial-data {:target c})

        (testing "fixture data gets put into the DOM"
          (is (= "foobar" (text (sel1 c :ul)))))

        ; You can add more tests in this manner, then finally call 'done'.
        (done)))))

上述英文代码中采取的步骤:

  1. Writeasync-call的模拟 fn 返回一个预先填充有夹具数据的通道(与原始接口相同的接口)。
  2. 模拟出原始 fn(您需要引用它或完全限定 ns)。
  3. 为单元测试目的创建一个新的虚拟 DOM。
  4. 指定不是来自 API 的模拟数据(如果有)。
  5. 将你的组件渲染到 DOM 中(这将async-callom/will-mount运行fixture-data时调用,去掉chan)。
  6. 观察 DOM 内容。
于 2016-01-11T23:43:28.243 回答