预备知识
Vue + VS Code + helloworld
HTML & JavaScript & CSS语法 - w3cschool
ECMAScript 6入门 - w3school
ECMAScript 6入门 - 阮一峰
Vue2 官方教程
Vuex 官方教程
sass 教程
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。 也就是说,ES6就是ES2015
Javascript和ECMAScript并不一样。ECMAScript是一种脚本在语法和语义上的标准,主要包括:语法、类型、语句、关键字、保留字、操作符、对象等, 跟浏览器没任何关系。Javascript是基于ECMAScript标准实现的。Javascript不仅仅包括ECMAScript,它还包含了DOM和BOM; DOM(Document Object Model)是HTML和XML的应用程序接口(API),W3C的标准即事为它而制定。BOM(Browser Object Model)是提供与浏览器进行交互的方法和接口,由于不同的浏览器实现方法不同,从而表现也可能不同。且BOM的核心是window对象,而window又是一个全局对象,这就意味着网页中定义的任何对象、变量、函数都是以window作为全局对象的。并且可以这么说,BOM是包含了DOM。
jest.mock
待测JS类:
// MyLodash.js
import _ from 'lodash';
export default class MyLodash {
constructor(name) {
this.name = name;
}
getName() {
const users = [
{ user: 'barney', active: false },
{ user: 'fred', active: false },
{ user: 'pebbles', active: true },
];
return _.findIndex(users, function(o) { return o.user === 'barney'; });
}
getName2() {
return 'bob2';
}
}
如果要MOCK掉_.findIndex,可以使用如下方法:
// MyLodash.spec.js
import MyLodash from '@/pilot/MyLodash';
jest.mock('lodash', () => ({
findIndex: () => {return 2},
}));
describe('MyLodash', () => {
test('test1', () => {
const ml = new MyLodash('a');
#console.log输出的值是mock的值2
console.log(ml.getName());
});
});
但上述代码无法判断mock的findIndex调用了多少次。更新如下:
import MyLodash from '@/pilot/MyLodash';
import _ from 'lodash';
const findIndexMock = jest.fn();
findIndexMock.mockReturnValue('222');
jest.mock('lodash');
_.findIndex = findIndexMock;
describe('MyLodash', () => {
test('test1', () => {
const ml = new MyLodash('a');
#console.log输出的值是mock的值222
console.log(ml.getName());
expect(findIndexMock).toHaveBeenCalledTimes(1);
});
});
window.URL.createObjectURL的mock
in jest, global is window. So if you want to use the window object, don't use global.window — just use global.
在测试代码里可以这样mock
describe('ApiManager', () => {
test('mock global window', () => {
global.URL.createObjectURL = jest.fn();
apiManager._downloadFile('a','testme', 'html');
expect(global.URL.createObjectURL).toHaveBeenCalledTimes(1);
});
});
单元测试的时候获取某些类的值
如果有些类或者对象很复杂,可以打开网页,在网页里找到这个值复制下来放到单元测试代码里,比自己创建这个对象快多了。
试了chrome和firefox,都可以的。
在复制拷贝的时候JONS.stringfy会提示cyclic object value,这时候可以通过如下方式解决,编写一个简单的函数,其中的circularReference就是提示cyclic object value的那个对象:
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123}
之后可以通过alert弹框展出出这个json对象。在浏览器里的console输出的JSON对象里面包含了大量的反斜杠。
mount和shallowmount
console.log(wrapper.html());打印的信息会有所不同
对于同样的如下源代码:
Yes
No
shallowmount的输出如下
Yes No
mount的输出如下
区别就是是否stub子组件
调试技巧
可以在源代码里加些console.log(), 在运行单元测试的时候查看是否会触发源代码里相应的console.log().
Reference
https://babeljs.io/docs/en/learn
https://www.manning.com/books/testing-vue-js-applications
https://alexjover.com/blog/test-methods-and-mock-dependencies-in-vue-js-with-jest/
https://vuejs.org/v2/cookbook/unit-testing-vue-components.html
https://engineering.doximity.com/articles/five-traps-to-avoid-while-unit-testing-vue-js
https://lmiller1990.github.io/vue-testing-handbook/computed-properties.html#testing-by-rendering-the-value
https://vue-test-utils.vuejs.org/
https://jestjs.io/docs/en/next/getting-started.html
https://github.com/eddyerburgh/avoriaz
https://github.com/alexjoverm/vue-testing-series
https://markus.oberlehner.net/blog/testing-vuex-powered-vue-components-with-jest/
https://alexjover.com/blog/test-deeply-rendered-vue-js-components-in-jest/