Open
Description
jest学习总结
最近要给项目添加单元测试,所以总结一下jest单元测试的语法点和单元测试的用意。
为什么要写单元测试
- 保持代码的可持续迭代
- 减少bug
- 减少调试时间
- 放心的进行重构
基本语法
相等判定
- toBe() => 实现原理是Object.is()
- toEqual() => 针对object
- not.toBe(). => 不相等
test('object assignment', () => {
const data = {one: 1}
data['two'] = 2
expect(data).toEqual({one: 1, two: 2})
})
test('two plus two is four', () => {
expect(2 + 2).toBe(4)
})
常见的false判定
- toBeNull() 只匹配null
- toBeUndefined 只匹配undefined
- toBeDefined 只要不是undefined
- toBeTruthy 只要是true可以
- toBeFalsy 只要是false就可以
test('null',() => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
// expect(n).toBeUndefined();
expect(n).toBeFalsy();
})
常见的数字判定
- toBeGreaterThan() 大于期待值
- toBeGreaterThanOrEqual() 大于或者等于期待值
- ToBeLessThan() 小于期待值
- toBeLessThanOrEqual() 小于或者等于期待值
- toBeCloseTo() 接近于这个值 0.1+0.2
test('Number', () => {
const value = 2 + 2;
const float = 0.1 + 0.2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(4);
expect(value).toBeLessThan(4.5);
expect(value).toBe(4);
expect(value).toEqual(4);
expect(float).toBeCloseTo(0.3);
})
字符串测试
- toMatch() 使用正则进行匹配
- not.toMatch() 不匹配
test('String', () => {
expect('team').not.toMatch(/I/);
expect('Chritshop').toMatch(/shop/);
})
数组
- toContain() 判定包含期待值
test('Array',() => {
const arr = [1,2,3,4,5];
expect(arr).toContain(3);
})
函数抛出错误
- toThrow() 抛出对应的错误
function compileCode() {
throw new Error('you are using the wrong JDK');
}
test('function', () => {
expect(compileCode).toThrow();
expect(compileCode).toThrow(Error);
expect(compileCode).toThrow('you are using the wrong JDK');
})
异步函数
callback
- callback验证
- 如果不添加done的回调函数,当我们的test函数执行完成后,异步还没有执行完,无法判定是否有错误。如果是同步的代码就不要添加done的回调函数
- 根据done()是否被调用来判定,是否返回的数据正常
// 同步执行,不需要添加done(可以简化)
function fetchDataSync(callback) {
callback('peanut butter');
}
test('sync callback', () => {
function callback(data) {
expect(data).toBe('peanut butter');
}
fetchDataSync(callback);
})
// 异步执行
function fetchData(callback) {
// 请求接口,1秒钟后返回数据
setTimeout(() => {
callback('peanut butter');
}, 1000)
}
// 如果不添加done的参数的时候,当callback被执行的时候,我们的test函数已经执行完成,不能判定是否有出错。
// jest根据是否done函数被执行来判定是否通过测试
test('the data is peanut butter', (done) => {
function callback(data) {
expect(data).toBe('peanut butter');
done()
}
fetchData(callback);
})
promises
- 记住一定要return promise的状态,不然等到我们test执行完成,异步的返回结果不知道是不是正确,得到不到测试
- 判定promise的reject方法执行,需要使用catch()方法
- 可以使用rejects和resolves属性来分别对promise的进行测试,它们会等待promise执行完成后再执行(记住返回状态), 不需要使用
expect.assertions(1)
function promiseFetchData() {
return new Promise((resolve, reject) => {
resolve('promise data')
})
}
test('async promise resolve', () => {
// expect.assertions(1);
return expect(promiseFetchData()).resolves.toBe('promise data');
})
test('the fetch fails with an error', () => {
return expect(fetchData()).rejects.toMatch('error');
});
assertions(1): 这里指的是断言必须只有一次,如果没有的话,就会报错,多余一次也会报错
Async/Await
- 使用常规的async和await,来判定数据是否正确
- 使用resolves和rejects属性来判定返回的promise
test('await syntax', async () => {
const data = await promiseFetchData()
expect.assertions(1);
expect(data).toBe('promise data')
})
test('await syntax fail', async () => {
expect.assertions(1);
try {
await errorPromise();
} catch (e) {
expect(e).toMatch('error')
}
})
安装和移除
beforeEach和afterEach
- 每执行一次单元测试test,都会触发beforeEach和afterEach的方法
- 可以用于异步请求接口,来初始化数据
function initializeCityDatabase(data) {
return new Promise((resolve) => {
resolve(data)
console.log(data)
})
}
beforeEach(() => {
console.log('beforeEach');
initializeCityDatabase('beforeEach-promise');
})
afterEach(() => {
console.log('afterEach');
})
test('test1', () => {
console.log('test)
expect('hcc').toBe('hcc')
})
test('test2', () => {
expect('hcc1').toBe('hcc1')
})
// 输出
beforeEach
beforeEach-promise
test
afterEach
beforeEach
beforeEach-promise
afterEach
beforeAll和afterAll
- 用于一次性的处理数据,一般用于全局请求一次接口的数据
describe作用域
- 一般before和after块,都会作用于整个文件,但是如果添加describe块来给测试用例分组,就只会作用于对应的describe块
- 顶层的before块会在describe块之前执行
function initializeCityDatabase(data) {
return new Promise((resolve) => {
resolve(data)
console.log(data)
})
}
beforeEach(() => {
console.log('beforeEach');
initializeCityDatabase('beforeEach-promise');
})
beforeAll(() => {
initializeCityDatabase('beforeAll-promise')
})
afterEach(() => {
console.log('afterEach');
})
afterAll(() => {
console.log('afterAll');
})
test('test1', () => {
console.log('test');
expect('hcc').toBe('hcc')
})
describe('代码块', () => {
beforeEach(() => {
console.log('describe beforeEach');
})
afterEach(() => {
console.log('describe afterEach');
})
test('', () => {
console.log('describe test')
})
})
beforeAll-promise
beforeEach
beforeEach-promise
test
afterEach
beforeEach
beforeEach-promise
describe beforeEach
describe test
describe afterEach
afterEach
¡afterAll
Metadata
Metadata
Assignees
Labels
No labels