假设存在如下代码
export default function fetchData(fn) {return Axios.get('http://www.dell-lee.com/react/api/demo.json')
}
接口返回的数据为
{"success": true
}
那么对于测试代码
test('fetchData', async () => {await expect(fetchData()).resolves.toMatchObject({data:{ success: true}})
})
执行逻辑大致等同于
test('fetchData', async () => {await fetchData().then(res => expect(res).toMatchObject({ data: { success: true } }));
})
以上两种测试代码只是在接口返回状态不为200时,测试用例报错提醒略有差异。
下面来具体看一下expect方法的执行逻辑。
expect方法返回expectation对象,该对象的方法为各种匹配器方法,以及加上.not/.resolves/.reject前缀的匹配器方法。
const expect = (actual, ...rest) => {/// ...const allMatchers = (0, _jestMatchersObject.getMatchers)();const expectation = {not: {},rejects: {not: {}},resolves: {not: {}}};const err = new JestAssertionError();Object.keys(allMatchers).forEach(name => {const matcher = allMatchers[name];const promiseMatcher = getPromiseMatcher(name, matcher) || matcher;expectation[name] = makeThrowingMatcher(matcher, false, '', actual);expectation.not[name] = makeThrowingMatcher(matcher, true, '', actual);expectation.resolves[name] = makeResolveMatcher(name,promiseMatcher,false,actual,err);expectation.resolves.not[name] = makeResolveMatcher(name,promiseMatcher,true,actual,err);expectation.rejects[name] = makeRejectMatcher(name,promiseMatcher,false,actual,err);expectation.rejects.not[name] = makeRejectMatcher(name,promiseMatcher,true,actual,err);});return expectation;
};
当我们调用.resolves.toMatchObject方法,其实就是执行makeResolveMatcher 方法的返回值函数。
makeResolveMatcher闭包内的函数其实就干了两件事。
1. 如果fetchData返回值actual不是一个promise,抛出异常。
2. 调用actual.then。如果走了成功的回调,那么就调用toMatchObject匹配器;如果走失败的回调就抛出异常。
const makeResolveMatcher = (matcherName, matcher, isNot, actual, outerErr) => (...args
) => {const options = {isNot,promise: 'resolves'};if (!isPromise(actual)) {throw new JestAssertionError(matcherUtils.matcherErrorMessage(matcherUtils.matcherHint(matcherName, undefined, '', options),`${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,matcherUtils.printWithType('Received',actual,matcherUtils.printReceived)));}const innerErr = new JestAssertionError();return actual.then(result =>makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply(null,args),reason => {outerErr.message =matcherUtils.matcherHint(matcherName, undefined, '', options) +'\n\n' +`Received promise rejected instead of resolved\n` +`Rejected to value: ${matcherUtils.printReceived(reason)}`;return Promise.reject(outerErr);});
};
.rejects.toMatchObject的执行逻辑也类似。
makeResolveMatcher闭包内的函数其实就干了两件事。
1. 如果fetchData返回值actual不是一个promise,抛出异常。
2. 调用actual.then。如果走了成功的回调就抛出异常;如果走失败的回调,那么就调用toMatchObject匹配器。
const makeRejectMatcher = (matcherName, matcher, isNot, actual, outerErr) => (...args
) => {const options = {isNot,promise: 'rejects'};if (!isPromise(actual)) {throw new JestAssertionError(matcherUtils.matcherErrorMessage(matcherUtils.matcherHint(matcherName, undefined, '', options),`${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,matcherUtils.printWithType('Received',actual,matcherUtils.printReceived)));}const innerErr = new JestAssertionError();return actual.then(result => {outerErr.message =matcherUtils.matcherHint(matcherName, undefined, '', options) +'\n\n' +`Received promise resolved instead of rejected\n` +`Resolved to value: ${matcherUtils.printReceived(result)}`;return Promise.reject(outerErr);},reason =>makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(null,args));
};
总结
所以所谓.resolves和.rejects其实就是一种简化写法,jest帮我们调用.then取出返回值与预测值进行比较。