[英]reactjs empty data when mocking axios.get with jestjs mock
我正在开发一个反应应用程序,我第一次决定实施测试。 我从更简单的组件开始,但我仍然遇到了麻烦,但现在我想测试更复杂的组件,尤其是通过 axios 调用 API。
我的应用程序如下所示:
import * as React from "react";
import Axios from "axios";
import { AnyData } from "../../interface/AnyDataInterface";
interface IProps {
}
interface IState {
loading: boolean | undefined,
myData: AnyData | undefined
}
export default class Home extends React.Component <IProps, IState> {
constructor (props: IProps){
super(props);
this.state = {
loading: true,
myData: {
field: undefined,
...
}
};
}
fetchData = ():void => {
this.setState({ loading: true });
Axios.get<AnyData>('my-url')
.then(res => {
if (res.status === 200 && res != null) {
this.setState({ myData:{... res.data} });
this.setState({ loading: false });
} else {
console.log('problem when fetching the logs from backend');
}
})
.catch(error => {
console.log(error);
});
}
render():JSX.Element {
return(
<div className="container">
<div>
<button role="button" onClick={this.fetchData}>Search</button>
</div>
{this.state.loading == true ? <p>Wait</p>:
<div role="composite">
{ Some child component that will render data }
</div>
}
</div>
);
}
}
我的测试如下所示:
import axios from 'axios';
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import Home from './Home';
jest.mock('axios');
describe('Home component', () => {
test('it can be clicked', async () => {
const fakeData = [{
some_field: some_data,
...
}];
axios.get = jest.fn().mockResolvedValue(() =>
Promise.resolve({data: fakeData}));
render(<Home />);
fireEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(axios.get).toBeCalledWith("my-url");
});
await waitFor(() => {
//Both expect should pass, if the title is there the data should also appear
expect(screen.getByText('some title text')).toBeInTheDocument(); //Pass without error
expect(screen.getByText('the data from fakeData that should be there')).toBeInTheDocument(); //Send me an error because jest is unable to find some_data
});
});
});
当我编写这个测试时,它每次都失败,但问题不在我的测试中,问题出在我的数据获取函数中。 在.then
我有一个条件如下: if (res.status === 200 && res != null) {
而res.status === 200
是一个从未满足的条件。
所以我删除了这个条件,通话正常进行。 但是我不得不更改我通常没有问题的代码的一部分,有没有办法模拟响应的状态呢? 这样我就可以把这个条件放回我的函数中。
我现在出现了另一个问题,在我的测试中,我的组件很好地显示了“点击后”的信息,但是出现的每个字段都有其相应的空数据,数据似乎没有通过,尽管.then
通过并且没有将我发送到.catch
。
对我来说奇怪的是,通过在我的数据获取函数中删除条件res.status === 200
并保留条件res != null
,测试仍然通过(同样的空数据问题)。 最后,通过添加一个console.log("data: ", res);
在我的.then
在我的组件的 fetch data 函数中,当测试执行时,我得到以下日志: data: [Function (anonymous)]
。
我不知道这是否可以解释这种行为,但我的测试是在 javascript 中,而我的类和函数是在打字稿中。 但是我在测试中填写的数据具有正确的形式(与我班级中请求的类型相同)所以打字稿应该看到类型匹配并且没有特别的问题
如果有人知道如何回答这些问题中的任何一个,那真的会对我有所帮助,我已经在这个测试上拖延了一段时间,它开始让我发疯。
编辑:
我刚刚意识到,在我的组件中的 fetchData() 中,我试图访问res.data
但我在测试中发送的假数据采用fakeData = [{...}]
的形式。 这可能是我的对象为空的原因吗?
我试图在我的测试中将这个假数据更改为: fakeData = [{ data: { ...}}]
但是我在调用axios的get方法时仍然遇到空响应的问题。
编辑:
我尝试将测试文件更改为 .tsx 文件,并将测试中的“fakeData”更改为:
jest.mock('axios');
describe('Home component', () => {
test('it can be clicked', async () => {
const fakeData: AnyData = {
"some_field": some_data,
...
};
const fakeConfig: AxiosRequestConfig<any> = {
"maxBodyLength": -1
};
const fakeHeaders: AxiosResponseHeaders= {
"access-control-allow-credentials": "true",
"access-control-allow-headers": "*",
"access-control-allow-methods": "*",
"access-control-allow-origin": "some-url",
"access-control-expose-headers": "scrollId",=
"content-type": "application/json; charset=utf-8",
....
"x-powered-by": "Express"
}
const res: AxiosResponse<AnyData, any> = {
config: fakeConfig,
data: fakeData,
headers: fakeHeaders,
status: 200,
statusText: "OK",
};
axios.get = jest.fn().mockResolvedValue(() =>
Promise.resolve({res: res}));
render(<Home />);
fireEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(axios.get).toBeCalledWith("my-url");
});
...
});
});
但即使使用这种方法,它仍然不起作用,但我真的觉得问题出在我发送的数据的格式上,我看不出我的数据与fetchData()
中请求的数据有何不同。 至于我数据中的字段,我确定它们很好,所以我猜问题出在res.data
的读取上。
当我通过将myData
的console.log
放入fetchData()
进行新测试时,我得到以下数据: { some_field: undefined, ... }
如果您花时间帮助我,请提前致谢。
我终于在考试中意识到了自己的错误。 这是在重写 axios.get 方法。
有效的代码如下:
jest.mock('axios');
describe('Home component', () => {
test('it can be clicked', async () => {
const fakeData: AnyData = {
"some_field": some_data,
...
};
const fakeConfig: AxiosRequestConfig<any> = {
"maxBodyLength": -1
};
const fakeHeaders: AxiosResponseHeaders= {
"access-control-allow-credentials": "true",
"access-control-allow-headers": "*",
"access-control-allow-methods": "*",
"access-control-allow-origin": "some-url",
"access-control-expose-headers": "scrollId",=
"content-type": "application/json; charset=utf-8",
....
"x-powered-by": "Express"
}
const res: AxiosResponse<AnyData, any> = {
config: fakeConfig,
data: fakeData,
headers: fakeHeaders,
status: 200,
statusText: "OK",
};
(axios.get as jest.Mock).mockResolvedValue(res); //THE LINE THAT CHANGE EVERYTHING
render(<Home />);
fireEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(axios.get).toBeCalledWith("my-url");
});
...
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.