用 Jest 测试 Axios
Posted
技术标签:
【中文标题】用 Jest 测试 Axios【英文标题】:Testing Axios in Jest 【发布时间】:2020-11-24 08:21:35 【问题描述】:我是测试新手。 我正在尝试测试异步数据获取功能,但我无法弄清楚为什么测试没有通过。 我开玩笑地模拟了 Axios,并为 Axios 的 get 方法提供了一个模拟实现来解决一个承诺。 错误说它无法读取 name 的属性,这意味着我认为数据 obj 未定义。
这里是 Yelp.test.js
import Yelp from './Yelp';
import axios from 'axios';
jest.mock('axios');
describe('searchRestaurantsInfo', () =>
test('returns object with restaurant infos', async () =>
const data =
name: 'Casa Romana',
address: '5 Albion Street',
coordinates: lat: 52.6322649, lng: -1.1314474 ,
city: 'Leicester LE1 6GD',
rating: 4.5,
photos: [
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
],
phone: '+441162541174',
price: '£££',
categories: 'Italian',
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_lookup&utm',
reviews: [
id: 'i_Q39aN9hwZzGDUb-IWpYw',
rating: 5,
text:
'Proper Italian restaurant. Not Italian-themed, or serving Italian fusion cuisine, just a place with an Italian owner who makes solid, straightforward...',
time_created: '2014-10-02 03:49:36',
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&hrid=i_Q39aN9hwZzGDUb-IWpYw&utm_campaign=yelp_api_v3&utm_me',
user:
id: '6tPD46XZSFllvgn2vTh51A',
image_url:
'https://s3-media3.fl.yelpcdn.com/photo/A4Ww6Ks2P9WsALqOFy9cOA/o.jpg',
name: 'Espana S.',
profile_url:
'https://www.yelp.com/user_details?userid=6tPD46XZSFllvgn2vTh51A',
,
,
],
;
axios.get.mockImplementationOnce(() => Promise.resolve(data));
await expect(
Yelp.searchRestaurantsInfo('q_IoMdeM57U70GwqjXxGJw')
).resolves.toEqual(data);
);
);
还有 Yelp.js
import axios from 'axios';
let YELP_API_KEY = process.env.REACT_APP_YELP_API_KEY;
const Yelp =
// Provides infos about a single restaurant
async searchRestaurantsInfo(id)
try
let response = await axios.get(
`https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/businesses/$id`,
headers:
Authorization: `Bearer $YELP_API_KEY`,
'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Allow-Origin': '*',
,
);
let responseRew = await axios.get(
`https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/businesses/$id/reviews`,
headers:
Authorization: `Bearer $YELP_API_KEY`,
'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Allow-Origin': '*',
,
);
const parameters =
name: response.data.name,
address: response.data.location.display_address[0],
coordinates:
lat: response.data.coordinates.latitude,
lng: response.data.coordinates.longitude,
,
city: response.data.location.display_address[1],
rating: response.data.rating,
photos: response.data.photos,
phone: response.data.phone,
price: response.data.price,
categories: response.data.categories[0].title,
url: response.data.url,
reviews: responseRew.data.reviews,
;
console.log( parameters, id );
return parameters;
catch (e)
console.log(e);
return e;
我得到的错误是
searchRestaurantsInfo
× returns array of restaurnats obj (66ms)
● searchRestaurantsInfo › returns array of restaurnats obj
expect(received).resolves.toEqual(expected) // deep equality
- Expected
+ Received
- Object // data object. I removed it from this error message because too long
+ [TypeError: Cannot read property 'name' of undefined]
47 | await expect(
48 | Yelp.searchRestaurantsInfo('q_IoMdeM57U70GwqjXxGJw')
> 49 | ).resolves.toEqual(data);
| ^
50 | );
51 | );
52 |
at Object.toEqual (node_modules/react-scripts/node_modules/expect/build/index.js:202:20)
at Object.<anonymous> (src/helpers/Yelp.test.js:49:16)
console.log src/helpers/Yelp.js:91
TypeError: Cannot read property 'name' of undefined
at Object.searchRestaurantsInfo (C:\Users\Turi\Desktop\project\RestaurantsRedux\src\helpers\Yelp.js:72:29)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at Object.<anonymous> (C:\Users\Turi\Desktop\project\RestaurantsRedux\src\helpers\Yelp.test.js:47:5)
提前感谢您的帮助!
【问题讨论】:
我只是在这里猜测,但也许你需要在那些地方传递 data
而不是 data
?
@tanmay 不,同样的错误。
应该是axios.get.mockImplementationOnce(() => Promise.resolve( data )
。有 2 个请求,但只有一个模拟,应该有更多。顺便说一句,捕捉错误并返回它不是常规的。
【参考方案1】:
您等待结果的方式可能有问题(可能是编译问题),请尝试像这样编写测试。
// note make sure the test() function is async
const result = await Yelp.searchRestaurantsInfo('q_IoMdeM57U70GwqjXxGJw')
expect(result).toEqual(data);
【讨论】:
【参考方案2】:我已经设法找到了解决方案。
就像建议的那样,我必须添加另一个模拟,因为在函数中有两个不同的请求。
除此之外,我意识到我不能同时使用data
axios.get.mockImplementationOnce(() => Promise.resolve(data));
和
Yelp.searchRestaurantsInfo('q_IoMdeM57U70GwqjXxGJw')
).resolves.toEqual(data);```
因为该函数没有返回data
,而是一个包含data
中某些部分的对象。
因此我创建了一个新对象params
与函数返回的对象进行比较。
import Yelp from './Yelp';
import axios from 'axios';
jest.mock('axios');
describe('searchRestaurantsInfo', () =>
test('returns object with restaurant infos', async () =>
const response =
data:
name: 'Casa Romana',
location:
display_address: [
"12 Upper Saint Martin's Lane",
'London WC2H 9FB',
'United Kingdom',
],
,
coordinates: latitude: 52.6322649, longitude: -1.1314474 ,
rating: 4.5,
photos: [
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
],
phone: '+441162541174',
price: '£££',
categories: [ alias: 'indpak', title: 'Indian' ],
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_lookup&utm',
,
;
const responseRev =
data:
reviews: [
id: 'i_Q39aN9hwZzGDUb-IWpYw',
rating: 5,
text:
'Proper Italian restaurant. Not Italian-themed, or serving Italian fusion cuisine, just a place with an Italian owner who makes solid, straightforward...',
time_created: '2014-10-02 03:49:36',
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&hrid=i_Q39aN9hwZzGDUb-IWpYw&utm_campaign=yelp_api_v3&utm_me',
user:
id: '6tPD46XZSFllvgn2vTh51A',
image_url:
'https://s3-media3.fl.yelpcdn.com/photo/A4Ww6Ks2P9WsALqOFy9cOA/o.jpg',
name: 'Espana S.',
profile_url:
'https://www.yelp.com/user_details?userid=6tPD46XZSFllvgn2vTh51A',
,
,
],
,
;
const params =
name: 'Casa Romana',
address: "12 Upper Saint Martin's Lane",
coordinates: lat: 52.6322649, lng: -1.1314474 ,
city: 'London WC2H 9FB',
rating: 4.5,
photos: [
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
'https://s3-media1.fl.yelpcdn.com/bphoto/4VUq4j1FF-n5bgXjtoC0Xw/o.jpg',
],
phone: '+441162541174',
price: '£££',
categories: 'Indian',
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_lookup&utm',
reviews: [
id: 'i_Q39aN9hwZzGDUb-IWpYw',
rating: 5,
text:
'Proper Italian restaurant. Not Italian-themed, or serving Italian fusion cuisine, just a place with an Italian owner who makes solid, straightforward...',
time_created: '2014-10-02 03:49:36',
url:
'https://www.yelp.com/biz/casa-romana-leicester?adjust_creative=7GHt4FY-2vjNyIPhQV7wcw&hrid=i_Q39aN9hwZzGDUb-IWpYw&utm_campaign=yelp_api_v3&utm_me',
user:
id: '6tPD46XZSFllvgn2vTh51A',
image_url:
'https://s3-media3.fl.yelpcdn.com/photo/A4Ww6Ks2P9WsALqOFy9cOA/o.jpg',
name: 'Espana S.',
profile_url:
'https://www.yelp.com/user_details?userid=6tPD46XZSFllvgn2vTh51A',
,
,
],
;
axios.get.mockImplementationOnce(() => Promise.resolve(response));
axios.get.mockImplementationOnce(() => Promise.resolve(responseRev));
await expect(
Yelp.searchRestaurantsInfo('q_IoMdeM57U70GwqjXxGJw')
).resolves.toEqual(params);
);
);
【讨论】:
以上是关于用 Jest 测试 Axios的主要内容,如果未能解决你的问题,请参考以下文章
Nest JS - 为返回 Observable Axios 响应的函数编写 Jest 测试用例的问题
如何在 React 应用程序中使用 JEST 测试向 api 发出 axios 请求的异步函数