【问题标题】:How to test react image component that gets it's src attribute from a REST api如何测试从 REST api 获取它的 src 属性的反应图像组件
【发布时间】:2021-10-23 20:16:17
【问题描述】:

我有一个来自 JS 类的实例“客户端”,如下所示:

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 属性集。我该怎么做?

【问题讨论】:

  • 您是否尝试过使用await waitFor(() =&gt; expect(image).toHaveAttribute('src', 'personImage'))

标签: javascript reactjs jestjs react-testing-library


【解决方案1】:

在测试用例的函数范围内,使用jest.mock()方法不会被提升到代码顶部(在任何es6之前import)。这意味着导入的./Person 组件在执行测试用例时将使用原始的./service/Client 模块。模拟晚了。

来自Using with ES module imports

如果您使用 ES 模块导入,那么您通常倾向于将导入语句放在测试文件的顶部。但通常你需要在模块使用之前指示 Jest 使用模拟。因此,Jest 会自动将 jest.mock 调用提升到模块顶部(在任何导入之前)。

所以你有两个选择:

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"

【讨论】:

  • 谢谢。我有点摆弄了第二个选项。
猜你喜欢
  • 2020-12-01
  • 2021-12-21
  • 2016-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
相关资源
最近更新 更多