单元测试与单元测试框架 Jest
今天节目的主要内容
- 什么是单元测试?
- Jest 简介
- 实际案例分析
测试是一种验证我们的代码是否可以按预期工作的手段。
单元测试特指被测试对象为程序中最小组成单元的测试。
开发简单
执行速度快
有助于促进我们更好地设计代码
单元测试的优势
单元测试的限制/不足
再简单的代码也需要开发,需要平衡投入与收益
容易给开发人员带来错觉
什么时候编写单元测试?
开发代码的时候
维护代码的时候
单元测试中的基本概念
- 被测试的对象是什么
- 要测试该对象的什么功能
- 实际得到的结果
- 期望的结果
- mock / spy (下文会详述)
单元测试的基本步骤
- 准备阶段:构造参数,创建 spy 等
- 执行阶段:用构造好的参数执行被测试代码
- 断言阶段:用实际得到的结果与期望的结果比较,以判断该测试是否正常
- 清理阶段:清理准备阶段对外部环境的影响,移除在准备阶段创建的 spy 等
Jest
Jest 是 Facebook 开发的一款 JavaScript 测试框架。在 Facebook 内部广泛用来测试各种 JavaScript 代码。
- 轻松上手
- 内置强大的断言与 mock 功能
- 内置测试覆盖率统计功能
- 内置 Snapshot 机制
describe('Addition', () => {
it('knows that 2 and 2 make 4', () => {
const val1 = 2;
const val2 = 2;
const result = val1 + val2;
const expectedResult = 4;
expect(result).toBe(expectedResult);
});
});

Jest 中的 mock 与 spy
function forEach(items, callback) {
for (let index = 0; index < items.length; index++) {
callback(items[index]);
}
}
describe('forEach', () => {
it('should call callback with each item', () => {
const callHistory = [];
const specialCallback = (...args) => callHistory.push(args);
forEach([1, 2], specialCallback);
expect(callHistory.length).toBe(2);
expect(callHistory[0][0]).toBe(1);
expect(callHistory[1][0]).toBe(2);
})
});
describe('forEach', () => {
it('should call callback with each item', () => {
const mockFn = jest.fn();
forEach([1, 2], mockFn);
expect(mockFn.mock.calls.length).toBe(2);
expect(mockFn.mock.calls[0][0]).toBe(1);
expect(mockFn.mock.calls[1][0]).toBe(2);
})
});
spy
const bot = {
sayHello: (name) => {
console.log(`Hello ${name}!`);
}
}
describe('bot', () => {
it('should say hello', () => {
const spy = jest.spyOn(bot, 'sayHello');
bot.sayHello('Michael');
expect(spy).toHaveBeenCalledWith('Michael');
spy.mockRestore();
})
});
案例分析
const domains = [
'img10.360buyimg.com',
'img11.360buyimg.com',
'img12.360buyimg.com',
'img13.360buyimg.com',
'img14.360buyimg.com',
];
const getImageDomain = (skuId) => {
if (skuId) {
return domains[skuId % 5];
} else {
return domains[Math.floor(Math.random() * 5)];
}
}
describe('getImageDomain', () => {
it('should select domain based on skuId if provided', () => {
expect(getImageDomain(1)).toBe('img11.360buyimg.com');
});
it('should select a random domain based on Math.random if skuId not available', () => {
const spy = jest.spyOn(Math, 'random').mockImplementation(() => 0.9);
expect(getImageDomain()).toBe('img14.360buyimg.com');
expect(spy).toHaveBeenCalled();
spy.mockRestore();
});
});
单元测试与单元测试框架 Jest
By loveky
单元测试与单元测试框架 Jest
- 1,159