jest 的工程文件后缀都是xx.test.js,咱们在运行一个jest工程的时候,jest会自动查找运行的后缀为*.test.js的脚本进行单元测试。前端
js 基于单线程异步的特性,在代码中充斥的异步程序和各类回调,因此咱们在测试异步代码的时候要格外注意。一下是各类异步的案例node
test('the data is peanut butter', () => {
function callback(data) {
expect(data).toBe('peanut butter');
}
fetchData(callback);
});
// 这种状况有问题,你们都知道一个ajax请求是一个事件(由两个事务发送和返回组成),当发送成功和返回成功这个事件就是完成的,就是成功的,这个时候jest就认为ajax事件完成了,因此检验会在回调判断执行前结束,没有验证data数据,因此这是有问题的。
复制代码
Jest 提供了相应的方法来done来解决这样的问题,确保回调执行的来完成整个test验证。 使用单个参数调用 done,而不是将测试放在一个空参数的函数。Jest会等done回调函数执行结束后,结束测试。 let's show codeajax
test('the data is peanut butter', done => {
function callback(data) {
expect(data).toBe('peanut butter');
done();
}
fetchData(callback);
});
若是 done()永远不会调用,这个测试将失败,这也是你所但愿发生的。
复制代码
test('Promise test', ()=>{
// 断言测试
expect.assertions(1);
// 必定记得return,不然测试拿不到promise的状态,测试会在fetchData()完成前完成。
return fetchData().then(data=>{
expect(data).tobe('promise')
})
})
复制代码
若是指望的promise是reject,咱们能够经过catch来捕获咱们的错误。 请确保添加 expect.assertions 来验证必定数量的断言被调用。 不然一个fulfilled态的 Promise 不会让测试失败。npm
test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(e => expect(e).toMatch('error'));
});
复制代码
// let's show code~ // resolves test('the data is peanut butter', () => { expect.assertions(1); return expect(fetchData()).resolves.toBe('peanut butter'); }); // rejects test('the fetch fails with an error', () => { expect.assertions(1); return expect(fetchData()).rejects.toMatch('error'); }); 复制代码
// 提早了解async和await的使用方法和场景
test('the data is peanut butter', async () => {
// 切记添加断言测试
expect.assertions(1);
const data = await fetchData();
expect(data).toBe('peanut butter');
});
test('the fetch fails with an error', async () => {
expect.assertions(1);
// 切记添加断言测试
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
复制代码
还能够混合使用.resolves / .rejects和Async/Await编程
// 由于await自己返回的就是一个promise。因此咱们能够在返回的promise的基础之上继续测试咱们的代码。
test('the data is peanut butter', async () => {
expect.assertions(1);
await expect(fetchData()).resolves.toBe('peanut butter');
});
test('the fetch fails with an error', async () => {
expect.assertions(1);
await expect(fetchData()).rejects.toMatch('error');
});
复制代码
#Jest的遍历 和 Setup 和 Teardown 进行一些重复的test设置的时候,咱们可使用beforeEach和afterEach。假设咱们在一个交互数据上须要重复的作一些测试设置。假如测试前调用initializeCityDatabase()和测试后调用clearCityDatabase()。那咱们就可使用beforeEach和afterEach了。 let's show code~数组
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
复制代码
beforeEach 和 afterEach处理异步的代码,一样能够采用done和promise,若是initializeCityDatabase()返回的是一个promise咱们能够这样处理他。let's show codepromise
beforeEach(()=>{
return initializeCityDatabase(); // return一个promise
})
复制代码
咱们能够经过Jest的describe函数,经过js函数式编程的思想来建立一个做用域,来模块化咱们的测试。具体场景就是的经过describe来模块咱们的foreach的做用范围。 let's show codebash
// 这里的beforeEach适用于全部的test
beforeEach(() => {
return initializeCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
describe('matching cities to foods', () => {
// 这里beforeEach仅仅适用于describe中的测试
beforeEach(() => {
return initializeFoodDatabase();
});
test('Vienna <3 sausage', () => {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
});
test('San Juan <3 plantains', () => {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});
复制代码
既然这么多beforeEach/afterEach和beforeAll/afterAll,那结合descibe来看看咱们的执行顺序。相信你们看完之后会想起js的(任务队列和做用域)。异步
beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));
test('', () => console.log('2 - test'));
});
// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll
正如结果查看顺序,全局的会做用到describe内部。 注意执行顺序,beforeALL和afterAll只会执行一次, 全局的beforeEach做用到了describe中的test,还要注意的是after做用域中的after比全局的after先执行。
beforeAll 在beforeEach前先执行,而afterAll在afterEach后执行。
复制代码
若是你想在众多的test中,仅仅想进行其中的一个test,很简单,你只要在他的test语句中添加.only标识就能够了,其余的测试则会跳过了.let's show codeasync
// 只有这个test会跑
test.only('this will be the only test that runs', () => {
expect(true).toBe(false);
});
// 这个test则会跳过
test('this test will not run', () => {
expect('A').toBe('A');
});
复制代码