javascript - Jest/Enzyme:如何处理在另一个内部调用的异步函数?
问题描述
我正在尝试运行 Jest/Enzyme 异步测试fetchTemperatures
,但我遇到了一些不熟悉的情况。如果我定义经度和纬度并注释掉,getUserCoordinates
我就能通过我的测试。问题是,我如何编写测试以允许/模拟其中的异步函数fetchTemperatures
正在返回值?
~ 另外,如果代码编写方式有任何其他问题,请告诉我,我正在尝试热身到 js 环境...
fetchTemperatures.js
export const fetchTemperatures = async (format = 'weather', source = 'openWeather') => {
// for 5-day-forecast set format arg to "forecast"
try {
let response;
const { longitude, latitude } = await getUserCoordinates();
//! the nested async above is preventing me from running the tests...
// let longitude = 100;
// let latitude = 100;
if (source === 'openWeather') {
response = await fetch(
`${openWeatherURL}/${format}?APPID=${process.env
.REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
);
} else if (source === 'darkSky') {
response = await fetch(
`${darkSkyURL}${process.env
.REACT_APP_DS_API_KEY}/${latitude},${longitude}?exclude=[currently,minutely,hourly,flags]`
);
} else {
//! is this getting hit? -- not sure
throw new Error("Enter a valid source string. Ex: 'openWeather' or 'darkSky'");
}
return await response.json();
} catch (error) {
throw new Error('Fetch failed');
}
};
fetchTemperatures.test.js
describe('fetchTemperatures()', () => {
let mockResponse = { data: 'Weather related data.' };
let response;
beforeAll(() => {
window.fetch = jest.fn().mockImplementation(() => {
return Promise.resolve({
ok: true,
json: () => Promise.resolve(mockResponse)
});
});
//! Number of calls: 0 === FIGURE OUT NESTED ASYNC IN SOURCE
response = fetchTemperatures();
});
// argument-based routes
it('args=default, should call fetch with the correct url', () => {
fetchTemperatures();
expect(window.fetch).toHaveBeenCalledWith(
`${openWeatherURL}/weather?APPID=${process.env
.REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
);
});
it('args="weather", should call fetch with the correct url', () => {
fetchTemperatures('forecast');
expect(window.fetch).toHaveBeenCalledWith(
`${openWeatherURL}/weather?APPID=${process.env
.REACT_APP_OW_API_KEY}&lat=${latitude}&lon=${longitude}&units=imperial`
);
});
it('args="weather", "darkSky", should call fetch with the correct url', () => {
fetchTemperatures('weather', 'darkSky');
expect(window.fetch).toHaveBeenCalledWith(
`${darkSkyURL}${process.env
.REACT_APP_DS_API_KEY}/${latitude},${longitude}?exclude=[currently,minutely,hourly,flags]`
);
});
// success
it('Success::Promise Resolve: should return with the current weather', () => {
response.then((results) => {
expect(results).toEqual(mockResponse);
});
});
// failure - success but response not ok
it('Failure::Response !ok: should return an error', () => {
window.fetch = jest.fn().mockImplementation(() => {
return Promise.resolve({
ok: false
});
});
expect(fetchTemperatures()).rejects.toEqual(Error('Fetch failed'));
});
// failure - reject
it('Failure::Promise Rejects', () => {
window.fetch = jest.fn().mockImplementation(() => {
return Promise.reject(Error('Fetch failed'));
});
expect(fetchTemperatures()).rejects.toEqual(Error('Fetch failed'));
});
});
解决方案
模拟很简单getUserCoordinates
,你有几个不同的选择:
- 您可以使用
jest.mock
,它获取包含并拦截它的模块的路径,getUserCoordinates
从您提供的回调中返回模拟值:
// This assumes `getUserCoordinates` is a named export.
// If it's the default export just have the callback return jest.fn()...
jest.mock('./get-user-coordinates.js', () => ({
getUserCoordinates: jest.fn().mockResolvedValue({lat: 0, long: 0});
}));
- 您还可以使用
import * as
,它允许您在没有以下情况下模拟导入jest.mock
:
// You can name `api` whatever you want
import * as api from './get-user-coordinates';
api.getUserCoordinates = jest.fn().mockResolvedValue({lat: 0, long: 0});
另一件事:在倒数第三个测试中,您应该确保return response.then()...
,否则您的测试将在等待进入.then()
块之前通过:
// Returning the promise makes the test wait until the
// `.then` is executed before finishing.
return response.then((results) => {
expect(results).toEqual(mockResponse);
});
推荐阅读
- vue.js - Nuxt JS i18n / 多语言无头 CMS
- javascript - React 条件渲染简化
- eclipse - Eclipse 的数字签名证书
- tkinter - 将树视图子项转移到 tkinter 中的另一个树视图
- c# - Unity - 设置脚本实例以使用另一个脚本中的类更新函数中的变量
- c# - 在 global.asax 中注册 .json 路由
- jboss - JBoss 没有重定向到 Keycloak
- javascript - how to give interface for joi-objectid?
- python - 从 sqlite 结果转换值
- python - 调试需要控制台输入的 Python 代码