vue jest unit test

1. Rendering: mountandshallowMount

1.1 mountandshallowMount

vue-test-utilsThere are two ways to render, or mount, a component— mountand shallowMount. A component that uses either of these two methods will return one wrapper, which is a contained Vue 组件object, supplemented with some methods useful for testing.

1.2 The difference between mountandshallowMount

  • mount: Will render child components
  • shallowMount: The subcomponent will be loaded, and the component will not be affected by the behavior properties of the subcomponent

Two, beforeEachandbeforeAll

2.1 Repeat setup for multiple tests

If you have some work that you want to repeat setup for multiple tests, you can use beforeEach and afterEach.
There is such a requirement that we need to call the method initializeCityDatabase() before each test, and call the method clearCityDatabase() after each test

beforeEach(() => {
    
    
  initializeCityDatabase();
});

afterEach(() => {
    
    
  clearCityDatabase();
});

test('city database has Vienna', () => {
    
    
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
    
    
  expect(isCity('San Juan')).toBeTruthy();
});

2.2 One-time setup

In some cases, you only need to do the setting once at the beginning of the file. While this setup behaves asynchronously, you're unlikely to handle it in one line. Jest provides beforeAll and afterAll to handle this situation.

beforeAll(() => {
    
    
  return initializeCityDatabase();
});

afterAll(() => {
    
    
  return clearCityDatabase();
});

test('city database has Vienna', () => {
    
    
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
    
    
  expect(isCity('San Juan')).toBeTruthy();
});

2.3 Scope

By default, before and after blocks apply to every test in the file. In addition, a certain block in the test can be grouped by the describe block. When the before and after blocks are inside the describe block, it is only applicable to the test inside the describe block.

3. Matcher

3.1 Matcher Basics

  • toBe: to judge whether it is equal
  • toBeNull: Determine whether it is null
  • toBeUndefined: Determine whether it is undefined
  • toBeDefined: Opposite to above
  • toBeNaN: Determine whether it is NaN
  • toBeTruthy: Determine whether it is true
  • toBeFalsy: Determine whether it is false
  • toContain: For arrays, check whether it contains
  • toHaveLength: For arrays, check the length of the array
  • toEqual: For objects, check whether they are equal
  • toStrictEqual: The function is similar to toEqual, but more strict
  • toThrow: abnormal match
  • toBeCalled: Whether the function was called
  • toHaveBeenCalledTimes: how many times the function is called
  • expect.assertions(n): Indicates that the expect code must be executed n times before execution is complete

3.2 Use of matchers

describe('Test', () => {
    
    
  // 判断是否相等
  expect(2 + 2).toBe(4);
  // 判断是否为null
  expect(null).toBeNull();
  // 判断是否为undefined
  expect(undefined).toBeUndefined();
  let a = 1;
  // 判断是否不为undefined
  expect(a).toBeDefined();
  a = 'ada';
  // 判断是否为NaN
  expect(a).toBeNaN();
  a = true;
  // 判断是否为true
  expect(a).toBeTruthy();
  a = false;
  // 判断是否为false
  expect(a).toBeFalsy();
  a = [1, 2, 3];
  // 数组用,检测是否包含
  expect(a).toContain(2);
  // 数组用,检测数组长度
  expect(a).toHaveLength(3);
  a = {
    
     a: 1 };
  // 对象用,检测是否相等
  expect(a).toEqual({
    
     a: 1 });
  // 功能与 toEqual 相似,但是更加严格
  expect(a).toStrictEqual({
    
     a: 1 });
  a = () => 1;
  // 函数是否被调用
  expect(a).toBeCalled();
  // 函数被调用几次
  expect(a).toHaveBeenCalledTimes(1);
});

3.3 The difference toStrictEqualwithtoEqual

toStrictEqual is similar in function to toEqual, but stricter. mainly reflects in:

  • Even if two objects have the same members but different prototype chains they are different.
  • undefined is not compatible with undefined.

3.4 expect.assertions(number)

Verify that a certain number of assertions are called during the test, this is often useful when testing asynchronous code, in order to ensure that assertions in callbacks are actually called.
Suppose we have a function doAsync which receives two callbacks callback1 and callback2 which will be called asynchronously in an unknown order.

test('doAsync calls both callbacks', () => {
    
    
  expect.assertions(2);
  function callback1(data) {
    
    
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    
    
    expect(data).toBeTruthy();
  }
 
  doAsync(callback1, callback2);
});

4. Wrapper

  • Wrapper: Wrapper is a method that includes a mounted component or vnode and a method to test the component or vnode.
  • Wrapper.vm: This is the Vue instance. You can access all methods and properties of an instance through wrapper.vm.
  • Wrapper.classes: Returns whether to own the dom of the class or an array of class names.
  • Wrapper.find: Return the first dom that satisfies the condition.
  • Wrapper.findAll: Return all doms that meet the conditions.
  • Wrapper.html: Returns the html string.
  • Wrapper.text: Returns the content string.
  • Wrapper.setData: Set the initial data of the component.
  • Wrapper.setProps: Set the initial props data of the component.
  • Wrapper.trigger: Used to trigger events.

5. Simulation function

5.1 Simulation functions

  • jest.fn(): Generate a mock function that can be used to replace the third-party function used in the source code
  • mockFn.mockImplementation(fn): accepts a function that should be used as the mock's implementation
  • mockFn.mockImplementationOnce(fn): accepts a function that will be used as the mock implementation for one call to the mocked function
  • mockFn.mockReturnValue(value): Used to define the default value returned every time the specified function is called
  • mockFn.mockReturnValueOnce(value)
  • mockFn.mockResolvedValue(value): Used to define 异步the default value returned every time the specified function is called
  • mockFn.mockResolvedValueOnce(value)

5.2 mockImplementationOnce()

const myMockFn = jest.fn(() => 'default')
  .mockImplementationOnce(() => 'first call')
  .mockImplementationOnce(() => 'second call');

console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
// 'first call', 'second call', 'default', 'default'

6. mock system

6.1 Commonly used mock methods

In unit testing, many times you don’t want to change the original code logic because you pass the test, or you just want to simply obtain a piece of data to test smoothly. At this time, you need to manually mock the data. Jest provides a powerful mock system. In the global Jest object, there are three commonly used mock methods:

  • jest.fn(implementation): Returns a mock function, where implementation is optional, representing the mock implementation of the mock function.
  • jest.mock(moduleName, factory, options): Used to mock some modules or files.
  • jest.spyOn(object, methodName): Return a mock function, which is similar to jest.fn, but can track the calling information of object[methodName]. If object[methodName] is not a function, an error will be reported.

6.2 is.fn()

Jest.fn() is the easiest way to create a mock function. If the internal implementation of the function is not defined, jest.fn() will return undefined as the return value.
The Mock function created by Jest.fn() can also set the return value, define the internal implementation or return the Promise object.

6.3 is.mock()

6.3.1 Automatically mock using jest.mock

jest.mock('./utils.ts') Automatically returns a mock that can be used to monitor calls to the class constructor and 所有方法its properties.

6.3.2 jest.mock() mock module directly in the unit test

jest.mock(path, moduleFactory)Accepts module factory arguments. A module factory is a function that returns a mock. In order to mock a constructor, a module factory must return a constructor. In other words, a module factory must be a function returning a function - a higher order function (HOF).

jest.mock('fs', () => ({
    
    
    readFileSync: jest.fn()
}))

6.3.3 Create a directory __mocks__ near the module directory that needs to be mocked

6.3.4 Examples

// utils.js
export default {
    
    
  add(a, b) {
    
    
    console.log('---------------util.js add----------');
    return a + b;
  }
};
// mock.js
import utils from './utils';
export default {
    
    
  test() {
    
    
    console.log('---------------mock.js test----------');
    return utils.add(1, 2);
  }
};
// mock.test.js
import m from './mock';
import utils from './utils';
jest.mock('./utils.js');
it('mock 整个 fetch.js模块', () => {
    
    
  m.test();
  expect(utils.add).toBeCalledTimes(1);
});

6.4 is.spyOn()

The jest.spyOn() method also creates a mock function, but the mock function can not only capture the calling of the function, but also execute the spyed function normally. In fact, jest.spyOn() is syntactic sugar for jest.fn(), which creates a mock function with the same internal code as the spyed function.

import m from './mock';
import utils from './utils';
it('mock 整个 fetch.js模块', () => {
    
    
  const y = jest.spyOn(utils, 'add');
  m.test();
  expect(y).toBeCalledTimes(1);
});
  • When using jest.mock()the add method is actually 没有执行, jest.spyOn()when using add会被执行

Seven, wrapper.emitted()

Each mounted wrapper will automatically log all fired events through the Vue instance behind it. You can retrieve these event records with the wrapper.emitted() method.

wrapper.vm.$emit('foo')
wrapper.vm.$emit('foo', 123)
/*
`wrapper.emitted()` 返回以下对象:
{
  foo: [[], [123]]
}
*/

// 断言事件已经被触发
expect(wrapper.emitted().foo).toBeTruthy()

// 断言事件的数量
expect(wrapper.emitted().foo.length).toBe(2)

// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])

You can also call wrapper.emittedByOrder() to get an array of events sorted by firing order.

reference

Guess you like

Origin blog.csdn.net/letianxf/article/details/128399853