如何测试从 REST api 获取其 src 属性的 React 图像组件
How to test react image component that gets it's src attribute from a REST api
我有一个来自 JS class 的实例 'client',如下所示:
class Client {
async fetchRandomUser() {
let response = await fetch("https://randomuser.me/api/?gender=male")
if (response.status >= 400) {
throw new Error("Error fetching random user");
}
return (await response.json()).results[0];
}
}
然后我有一个像这样的 React 组件:
import React from 'react';
import client from "./service/Client";
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {image: ''}
}
async componentDidMount() {
const user = await client.fetchRandomUser();
this.setState({image: user.picture.large});
}
setError(error) {
return this.setState({errorStatus: error});
}
render() {
return (
<img src={this.state.image} width="128" height="128"/>
);
}
}
export default Person;
还有一个测试:
import React from "react";
import { render, screen, waitFor } from '@testing-library/react';
import Person from './Person';
test('fetches image from random user API', async () => {
const mockFetchRandomUser = jest.fn().mockImplementation(async () => Promise.resolve({picture:{large: 'personImage'}}));
jest.mock("./service/Client", () => {
return {
fetchRandomUser: mockFetchRandomUser
};
});
const {container} = render(<Person data-testid="person"/>);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== "").toBeTruthy())
.then(() => {
screen.debug(image);
expect(mockFetchRandomUser).toHaveBeenCalledTimes(1);
});
});
在此测试中,我无法获取 waitFor 或 findByRole 或任何与此相关的东西,以等待标签获得其 src 属性集。我该怎么做?
在测试用例的函数范围内,使用jest.mock()
方法不会被提升到代码顶部(在任何es6 import
之前)。这意味着导入的 ./Person
组件将在执行测试用例时使用原始的 ./service/Client
模块。模拟晚了。
来自 Using with ES module imports:
If you're using ES module imports then you'll normally be inclined to put your import statements at the top of the test file. But often you need to instruct Jest to use a mock before modules use it. For this reason, Jest will automatically hoist jest.mock
calls to the top of the module (before any imports).
所以你有两个选择:
1.在测试用例功能范围内调用 jest.mock()
后,使用 import()
动态导入模块。
Person.test.jsx
:
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
test('fetches image from random user API', async () => {
jest.mock('./service/Client');
const Person = (await import('./Person')).default;
const client = (await import('./service/Client')).default;
client.fetchRandomUser.mockResolvedValueOnce({ picture: { large: 'personImage' } });
render(<Person data-testid="person" />);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== '').toBeTruthy());
expect(client.fetchRandomUser).toHaveBeenCalledTimes(1);
});
2。在测试文件的模块范围内使用jest.mock()
,然后你可以使用静态import
导入模块
Person.test.jsx
:
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import Person from './Person';
import client from './service/Client';
jest.mock('./service/Client');
test('fetches image from random user API', async () => {
client.fetchRandomUser.mockResolvedValueOnce({ picture: { large: 'personImage' } });
render(<Person data-testid="person" />);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== '').toBeTruthy());
expect(client.fetchRandomUser).toHaveBeenCalledTimes(1);
});
jestjs 版本:"jest": "^26.6.3"
我有一个来自 JS class 的实例 'client',如下所示:
class Client {
async fetchRandomUser() {
let response = await fetch("https://randomuser.me/api/?gender=male")
if (response.status >= 400) {
throw new Error("Error fetching random user");
}
return (await response.json()).results[0];
}
}
然后我有一个像这样的 React 组件:
import React from 'react';
import client from "./service/Client";
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {image: ''}
}
async componentDidMount() {
const user = await client.fetchRandomUser();
this.setState({image: user.picture.large});
}
setError(error) {
return this.setState({errorStatus: error});
}
render() {
return (
<img src={this.state.image} width="128" height="128"/>
);
}
}
export default Person;
还有一个测试:
import React from "react";
import { render, screen, waitFor } from '@testing-library/react';
import Person from './Person';
test('fetches image from random user API', async () => {
const mockFetchRandomUser = jest.fn().mockImplementation(async () => Promise.resolve({picture:{large: 'personImage'}}));
jest.mock("./service/Client", () => {
return {
fetchRandomUser: mockFetchRandomUser
};
});
const {container} = render(<Person data-testid="person"/>);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== "").toBeTruthy())
.then(() => {
screen.debug(image);
expect(mockFetchRandomUser).toHaveBeenCalledTimes(1);
});
});
在此测试中,我无法获取 waitFor 或 findByRole 或任何与此相关的东西,以等待标签获得其 src 属性集。我该怎么做?
在测试用例的函数范围内,使用jest.mock()
方法不会被提升到代码顶部(在任何es6 import
之前)。这意味着导入的 ./Person
组件将在执行测试用例时使用原始的 ./service/Client
模块。模拟晚了。
来自 Using with ES module imports:
If you're using ES module imports then you'll normally be inclined to put your import statements at the top of the test file. But often you need to instruct Jest to use a mock before modules use it. For this reason, Jest will automatically hoist
jest.mock
calls to the top of the module (before any imports).
所以你有两个选择:
1.在测试用例功能范围内调用 jest.mock()
后,使用 import()
动态导入模块。
Person.test.jsx
:
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
test('fetches image from random user API', async () => {
jest.mock('./service/Client');
const Person = (await import('./Person')).default;
const client = (await import('./service/Client')).default;
client.fetchRandomUser.mockResolvedValueOnce({ picture: { large: 'personImage' } });
render(<Person data-testid="person" />);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== '').toBeTruthy());
expect(client.fetchRandomUser).toHaveBeenCalledTimes(1);
});
2。在测试文件的模块范围内使用jest.mock()
,然后你可以使用静态import
导入模块
Person.test.jsx
:
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import Person from './Person';
import client from './service/Client';
jest.mock('./service/Client');
test('fetches image from random user API', async () => {
client.fetchRandomUser.mockResolvedValueOnce({ picture: { large: 'personImage' } });
render(<Person data-testid="person" />);
const image = screen.getByRole('img');
await waitFor(() => expect(image.src !== '').toBeTruthy());
expect(client.fetchRandomUser).toHaveBeenCalledTimes(1);
});
jestjs 版本:"jest": "^26.6.3"