有比较好的前端JS TDD教程吗( 二 )
纯UI组件这类组件我们没有一个个去测试组件里面的元素,而是按照UX的要求build完组件以后加上一个jest的json snapshot测试。
注意这里的snapshot并不是大家印象中的e2e测试中的截图,而是jest里将组件render出来之后使用json生成一份UI的dom结构,在下次测试时,生成一份新的快照与旧的快照进行比对,从而得出两个UI不一样的地方,实现对UI的保护。 但是其实使用snapshot测试有两个问题:
snapshot相比较于一般的单元测试来说运行速度较慢,如果项目中大量使用的snapshot测试的话,在运行所有单元测试的时候会比较明显的感受到单元测试的速度被拖慢了,一定程度上违背了单元测试快速反馈的初衷;维护snapshot的人工成本较大,snapshot测试最大的问题在于你只要改动了任何UI的部分,这个测试都会挂掉,这个时候就需要仔细对比不同的地方以决定是更新snapshot还是改错地方了,而如果此时团队里有“省心”的队友无脑更新snapshot的话,这个测试相当于浪费了资源。// Content.test.tsx describe(\u0026#39;Content\u0026#39;, () =\u0026gt; { it(\u0026#39;should render correctly\u0026#39;, () =\u0026gt; { const {container} = render(\u0026lt;Content/\u0026gt;); expect(container).toMatchSnapshot(); }); }); // Content.test.tsx.snap // Jest Snapshot v1, https://goo.gl/fbAQLP exports = ` \u0026lt;div\u0026gt; \u0026lt;main class="prefix-layout-content" /\u0026gt; \u0026lt;/div\u0026gt; `; // Content.tsx export const Content: React.FC\u0026lt;React.HTMLAttributes\u0026lt;HTMLElement\u0026gt;\u0026gt; = (props) =\u0026gt; { const { className = \u0026#39;\u0026#39;, children, ...restProps } = props; return ( \u0026lt;main className={combineClass(\u0026#39;layout-content\u0026#39;, className)} {...restProps}\u0026gt; {children} \u0026lt;/main\u0026gt; ); };逻辑与UI混合组件这个部分我们就需要hooks的帮忙了,这样的组件不是UI和逻辑强耦合嘛,那我们就可以将两者拆开。于是这样的组件我们会这样写:
首先将UI页面build出来,但是需要的callback全部写成空函数 将所有callback或者是页面需要用到的逻辑抽到一个hook中 此时hook里的代码没有UI只有逻辑,故可以使用测试库对hook进行单独的逻辑测试,所以此时hook的开发可以按照逻辑组件的开发进行TDD 整个混合组件开发完成后,补上一个snapshot测试,需要注意的是可能该组件在渲染时需要一些数据,在写snapshot测试时应该确保准备的数据是完备的,否则快照会渲染出一份根本没有数据的错误组件 // usePageExample.test.ts import {act, renderHook} from "@testing-library/react-hooks"; describe(\u0026#39;usePageExample\u0026#39;, () =\u0026gt; { let mockGetUserId: jest.Mock; let mockValidate: jest.Mock; beforeAll(() =\u0026gt; { mockGetUserId = jest.fn(); mockValidate = jest.fn(); jest.mock(\u0026#39;../../../../request/someRequest\u0026#39;, () =\u0026gt; ({ getUserId: mockGetUserId, })); jest.mock(\u0026#39;../../../../validator/formValidator\u0026#39;, () =\u0026gt; ({ formValidate: mockValidate, })); }); afterAll(() =\u0026gt; { mockGetUserId.mockReset(); mockValidate.mockReset(); }); it(\u0026#39;should trigger request with test string when click button\u0026#39;, () =\u0026gt; { const {usePageExample} = require(\u0026#39;../usePageExample\u0026#39;); const {result} = renderHook(() =\u0026gt; usePageExample()); act(() =\u0026gt; { result.current.onClick(); }); expect(mockGetUserId).toBeCalled(); }); it(\u0026#39;should validate form values before submit\u0026#39;, () =\u0026gt; { const {usePageExample} = require(\u0026#39;../usePageExample\u0026#39;); const {result} = renderHook(() =\u0026gt; usePageExample()); const formValues = {id: \u0026#39;1\u0026#39;, name: \u0026#39;name\u0026#39;}; act(() =\u0026gt; { result.current.onSubmit(formValues); }); expect(mockValidate).toBeCalledWith(formValues); }); }); // usePageExample.ts import {getUserId} from "../../../request/someRequest"; import {formValidate} from "../../../validator/formValidator"; export interface IFormValues { email: string; name: string; } export const usePageExample = () =\u0026gt; { const onClick = () =\u0026gt; { getUserId(); }; const onSubmit = (formValues: IFormValues) =\u0026gt; { formValidate(formValues); }; return {onClick, onSubmit}; }; // PageExample.tsx import * as React from "react"; import {usePageExample} from "./hooks/usePageExample"; export const PageExample: React.FC\u0026lt;IPageExampleProps\u0026gt; = () =\u0026gt; { const {onClick, onSubmit} = usePageExample(); return ( \u0026lt;div\u0026gt; \u0026lt;form onSubmit={() =\u0026gt; onSubmit}\u0026gt; \u0026lt;input type="text"/\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;button onClick={onClick}\u0026gt;test\u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; ); };
推荐阅读
- 为啥知乎上普便有一种【我在北上广深打工,所以拥有更好的视野】这样的错觉
- 趣头条|你我皆风华正茂,拥有广汽三菱奕歌的日子是美好的
- 在上海陆家嘴附近工作,请问去哪边租房会比较好
- 设计专业学生上传自己的作品,用哪个网站比较好
- 言论自由|
- 学的自动化却对IT比较感兴趣。。感觉对自己的专业帮助不大,好苦恼,要不要继续是专精还是学点感兴趣的?
- 大三学生准备日本留学过程中要不要准备考研
- 100W——150W有啥好的车
- 肝硬化|肝不好的人,身体有什么异常,暗示肝硬化来了?肝病怕拖,早检查
- 电话营销机器人哪个比较好用
