前端自动化测试之Jest 进阶教程示例

2023-02-16 10:06:39
目录
Jest Mockmock 异步方法Mock TimersMock 类Snapshot 快照测试DOM 测试

Jest>

mock>
export const runCallback = callBack => {
  return callBack();
};

我们对上面的代码进行测试:

import { runCallback } from "./demo";
test("测试 runCallback", () => {
  const fn = jest.fn(); // mock函数,捕获函数的调用
  runCallback(fn);
  expect(fn).toBeCalled();
  // expect(runCallback(() => "hello")).toBe("hello");
});

通过 jest.fn 生成的 mock 函数,我们可以打印其 fn.mock,得到以下结果:

    calls 被调用的情况,通过 fn.mock.calls.length 可获取 mock 函数被调用次数,每个数组里存放传递给 mock 函数的参数instances jest.fn 生成函数的 this 指向invocationCallOrder 传递进去函数的执行顺序results 函数输出的结果
    // mock函数返回123,results的value变为123
    const fn = jest.fn(() => 123); 
    // 等价于
    fn.mockReturnValue("123");
    // 等价于
    fn.mockImplementation(() => 123);
    // 模拟返回一次函数结果
    fn.mockReturnValueOnce("123");
    // 等价于
    fn.mockImplementationOnce(() => 123);
    

    测试异步代码每次都发送真实请求,无疑是很慢的,我们可以使用 mock 模拟请求方法

      导出我们的请求方法
      // demo.js
      import axios from "axios";
      export function getData() {
        return axios.get("http://www.dell-lee.com/react/api/demo.json");
      }
      
        同级目录下建一个 **mocks** 的文件夹,建立同名的文件,此文件就是模拟请求的文件

        export function fetchData() {
          return Promise.resolve({
            success: true
          });
        }
        
          测试用例部分:
          // 模拟 request 模块
          jest.mock("./request.js"); // 也可以在 jest.config.js 里面手动设置 automock 为 true
          // 取消 mock
          // jest.unmock("./demo.js");
          import { fetchData } from "./request";
          test("测试 fetchData", () => {
            // 此请求实际会请求 __mocks__ 下的 request.js 方法
            return fetchData().then(data => {
              expect(data).toEqual({
                success: true
              });
            });
          });
          

          如果我们 request.js 某些方法不需要 mock

          const { getNumber } = jest.requireActual("./request.js");
          

          Mock>

          当我们有如下代码需要测试的时候:

          export default callback => {
            setTimeout(() => {
              callback();
            }, 3000);
          };
          

          测试:

          import timer from "./timer";
          test("测试 timer", done => {
            timer(() => {
              expect(1).toBe(1);
              done();
            });
          });
          

          我们不可能总是等待定时器完才去执行用例,这时候我们要用 Jest 来操作时间!步骤如下:

            通过 jest.useFakeTimers() 使用 jest "自制的" 定时器执行 timer 函数之后,快进时间 3 秒 jest.advanceTimersByTime(3000),这个方法可以调用任意次,快进的时间会叠加这时候我们已经穿梭到了 3 秒后,expect 也能生效了!
            import timer from "./timer";
            beforeEach(() => {
              jest.useFakeTimers();
            });
            test("测试 timer", () => {
              // jest.fn() 生成的是一个函数,这个函数能被监听调用过几次
              const fn = jest.fn();
              timer(fn);
              jest.advanceTimersByTime(3000);
              expect(fn).toHaveBeenCalledTimes(1);
            });
            

            Mock>
              当我们只关注类的方法是否被调用,而不关心方法调用产生的结果时,可以 mock 类

              util.js 中定义了 Util

              export class Util {
                a() {}
                b() {}
              }
              

              useUtil.js 调用这个类

              import { Util } from "./util";
              export function useUtil() {
                let u = new Util();
                u.a();
                u.b();
              }
              

              我们需要测试 u.au.b 被调用

              jest.mock("util.js") 会将 Util、Util.a、Util.b 都 mock 成 jest.fn

              jest.mock("util.js"); // mock Util 类
              import { Util } from "./util/util";
              import { useUtil } from "./util/uesUtil";
              test("util 的实例方法被执行了", () => {
                useUtil();
                expect(Util).toHaveBeenCalled();
                expect(Util.mock.instances[0].a).toHaveBeenCalled();
                expect(Util.mock.instances[0].b).toHaveBeenCalled();
              });
              

              Snapshot>
                将文件内容拍照一样拍下来。下次运行测试用例的时候,如果内容变化,则会报错

                config.js

                export const generateConfig = () => {
                  return {
                    server: "https://localhost",
                    port: 8080,
                    domain: "localhost"
                  };
                };
                

                测试用例部分:

                import { generateConfig } from "./config";
                test("测试 generateConfig", () => {
                  // 保存会生成 __snapshots__ 目录,记住配置相关内容
                  expect(generateConfig()).toMatchSnapshot();
                });
                

                改变 config 文件内容,测试不通过,按 u 可以更新快照

                如果有两个快照改变,我们需要一个个更新,我们可以按 i进入以下界面:

                s 先跳过此次测试用例

                u 可一个个更新快照内容,使得测试通过

                如果我们配置有不断变化的量:

                time: new Date()
                

                我们可以这样测试,保证 time 是一个 Date 类型即可

                test("测试 generateConfig", () => {
                  expect(generateConfig()).toMatchSnapshot({
                    time: expect.any(Date)
                  });
                });
                

                我们除了可以成目录保存快照内容,还可以生成行内快照,存放本文件即可

                test("测试 generateConfig", () => {
                  // 需要安装prettier
                  expect(generateConfig()).toMatchInlineSnapshot();
                });
                

                DOM>
                  jest 自己模拟了一套 jsDom api ,所以我们能使用 jest 测试 dom

                  dom.js

                  export function addDivToBody() {
                    const div = document.createElement("div");
                    document.body.appendChild(div);
                  }
                  

                  测试:

                  import { addDivToBody } from "./timer";
                  test("测试 addDivToBody", () => {
                    addDivToBody();
                    addDivToBody();
                    expect(document.body.querySelectorAll("div").length).toBe(2);
                  });

                  以上就是前端自动化测试之Jest 进阶教程示例的详细内容,更多关于Jest 前端自动化测试的资料请关注易采站长站其它相关文章!