当前位置:   article > 正文

vue jest单元测试_jest shallowmount

jest shallowmount

一、渲染: mountshallowMount

1.1 mountshallowMount

vue-test-utils 提供了两种方式用于渲染,或者说 加载(mount) 一个组件 — mountshallowMount。一个组件无论使用这两种方法的哪个都会返回一个 wrapper,也就是一个包含了 Vue 组件的对象,辅以一些对测试有用的方法。

1.2 mountshallowMount的区别

  • mount: 会渲染子组件
  • shallowMount:会加载子组件,不会被子组件的行为属性影响该组件

二、 beforeEachbeforeAll

2.1 为多次测试重复设置

如果你有一些要为多次测试重复设置的工作,可以使用beforeEach和afterEach。
有这样一个需求,需要我们在每个测试之前调用方法initializeCityDatabase(),在每个测试后,调用方法clearCityDatabase()

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

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

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

test('city database has San Juan', () => {
  expect(isCity('San Juan')).toBeTruthy();
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2.2 一次性设置

在某些情况下,你只需要在文件的开头做一次设置。这种设置是异步行为的时候,你不太可能一行处理它。Jest提供了beforeAll和afterAll处理这种情况。

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();
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.3 作用域

默认情况下,before和after的块可以应用到文件中的每一个测试。此外可以通过describe块来将将测试中的某一块进行分组。当before和after的块在describe块内部的时候,则只适用于该describe块内的测试。

三、匹配器

3.1 匹配器基础

  • toBe:判断是否相等
  • toBeNull:判断是否为null
  • toBeUndefined:判断是否为undefined
  • toBeDefined:与上相反
  • toBeNaN:判断是否为NaN
  • toBeTruthy:判断是否为true
  • toBeFalsy:判断是否为false
  • toContain:数组用,检测是否包含
  • toHaveLength:数组用,检测数组长度
  • toEqual:对象用,检测是否相等
  • toStrictEqual:功能与 toEqual 相似,但是更加严格
  • toThrow:异常匹配
  • toBeCalled: 函数是否被调用
  • toHaveBeenCalledTimes: 函数被调用几次
  • expect.assertions(n): 表示必须执行n次expect 代码才算执行完

3.2 匹配器使用

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);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

3.3 toStrictEqualtoEqual 的区别

toStrictEqual 的功能与 toEqual 相似,但是更加严格。主要体现在:

  • 即使两个对象的成员相同,但原型链不同则不同。
  • undefined 和未定义不兼容。

3.4 expect.assertions(number)

验证在测试期间调用了一定数量的断言,在测试异步代码时这通常很有用,以便确保回调中的断言确实被调用。
假设我们有一个函数doAsync,它接收两个回调callback1和callback2,它将异步地以一个未知的顺序调用它们。

test('doAsync calls both callbacks', () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }
 
  doAsync(callback1, callback2);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

四、Wrapper

  • Wrapper:Wrapper 是一个包括了一个挂载组件或 vnode,以及测试该组件或 vnode 的方法。
  • Wrapper.vm:这是该 Vue 实例。你可以通过 wrapper.vm 访问一个实例所有的方法和属性。
  • Wrapper.classes:返回是否拥有该class的dom或者类名数组。
  • Wrapper.find:返回第一个满足条件的dom。
  • Wrapper.findAll:返回所有满足条件的dom。
  • Wrapper.html:返回html字符串。
  • Wrapper.text:返回内容字符串。
  • Wrapper.setData:设置该组件的初始data数据。
  • Wrapper.setProps:设置该组件的初始props数据。
  • Wrapper.trigger:用来触发事件。

五、模拟函数

5.1 模拟函数

  • jest.fn():生成一个模拟函数,这个函数可以用来代替源代码中被使用的第三方函数
  • mockFn.mockImplementation(fn):接受一个函数,该函数应用作模拟的实现
  • mockFn.mockImplementationOnce(fn):接受一个函数,该函数将用作对被模拟函数的一次调用的模拟实现
  • mockFn.mockReturnValue(value):用于定义在指定函数的每一次调用时返回预设值
  • mockFn.mockReturnValueOnce(value)
  • mockFn.mockResolvedValue(value):用于定义在指定异步函数的每一次调用时返回预设值
  • 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'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

六、mock系统

6.1 常用的mock方法

在单元测试中,很多时候不想因为通过测试而改变原来的代码逻辑或者只是想简单地获取一个数据来顺利进行测试,这个时候就需要手动mock数据,Jest提供了一个强大的mock系统。在全局的Jest对象里,有三个常用的mock方法:

  • jest.fn(implementation):返回一个mock函数,其中implementation 为可选,代表mock函数的模拟实现。
  • jest.mock(moduleName, factory, options):用来mock一些模块或者文件。
  • jest.spyOn(object, methodName):返回一个mock函数,和jest.fn相似,但是能够追踪object[methodName]的调用信息,如果object[methodName]不是一个函数,则会报错。

6.2 jest.fn()

Jest.fn()是创建Mock函数最简单的方式,如果没有定义函数内部的实现,jest.fn()会返回undefined作为返回值。
Jest.fn()所创建的Mock函数还可以设置返回值,定义内部实现或返回Promise对象。

6.3 jest.mock()

6.3.1 使用 jest.mock 自动 mock

jest.mock('./utils.ts') 自动返回一个 mock ,可以使用它来监视对类构造函数及其所有方法的调用。

6.3.2 jest.mock()直接在单元测试里面mock 模块

jest.mock(path, moduleFactory) 接受模块工厂参数。模块工厂是一个返回模拟的函数。为了模拟构造函数,模块工厂必须返回构造函数。换句话说,模块工厂必须是返回函数的函数-高阶函数(HOF)。

jest.mock('fs', () => ({
    readFileSync: jest.fn()
}))
  • 1
  • 2
  • 3

6.3.3 在需要mock的模块目录临近建立目录__mocks__

6.3.4 样例

// 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);
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

6.4 jest.spyOn()

jest.spyOn()方法同样创建一个mock函数,但是该mock函数不仅能够捕获函数的调用情况,还可以正常的执行被spy的函数。实际上,jest.spyOn()是jest.fn()的语法糖,它创建了一个和被spy的函数具有相同内部代码的mock函数。

import m from './mock';
import utils from './utils';
it('mock 整个 fetch.js模块', () => {
  const y = jest.spyOn(utils, 'add');
  m.test();
  expect(y).toBeCalledTimes(1);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 使用jest.mock() 时add方法实际没有执行,使用jest.spyOn()时add会被执行

七、wrapper.emitted()

每个挂载的包裹器都会通过其背后的 Vue 实例自动记录所有被触发的事件。你可以用 wrapper.emitted() 方法取回这些事件记录。

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
// 断言事件已经被触发
expect(wrapper.emitted().foo).toBeTruthy()

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

// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

你也可以调用 wrapper.emittedByOrder() 获取一个按触发先后排序的事件数组。

参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/820700
推荐阅读
相关标签
  

闽ICP备14008679号