通过模拟请求使用异步 api 调用测试组件
Testing components with async api calls by mocking the request
我仍处于 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.test
有 async
块来测试异步代码,但所有示例都显示它测试实际代码块,其中只有 go
,而不是在更大的上下文中。
您可以使用模拟来测试您的组件:
(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)))))
以上英文代码所采取的步骤:
- 编写
async-call
的 mock fn,returns 通道(与原始通道相同的接口)预填充了夹具数据。
- mock出原来的fn(需要引用或者完全限定ns)
- 为单元测试目的创建一个新的虚拟 DOM。
- 指定不是来自 API 的模拟数据,如果有的话。
- 将您的组件渲染到 DOM(这将在
om/will-mount
运行时调用 async-call
,将 fixture-data
从 chan
中移除)。
- 观察DOM内容。
我仍处于 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.test
有 async
块来测试异步代码,但所有示例都显示它测试实际代码块,其中只有 go
,而不是在更大的上下文中。
您可以使用模拟来测试您的组件:
(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)))))
以上英文代码所采取的步骤:
- 编写
async-call
的 mock fn,returns 通道(与原始通道相同的接口)预填充了夹具数据。 - mock出原来的fn(需要引用或者完全限定ns)
- 为单元测试目的创建一个新的虚拟 DOM。
- 指定不是来自 API 的模拟数据,如果有的话。
- 将您的组件渲染到 DOM(这将在
om/will-mount
运行时调用async-call
,将fixture-data
从chan
中移除)。 - 观察DOM内容。