在React中测试API调用-状态未更新 [英] Testing API Call in React - State not updating

查看:70
本文介绍了在React中测试API调用-状态未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试组件中的API调用后状态是否已更新。我有一个方法可以说 method1(),在该方法中,它调用 fetch 并将状态设置为结果。
这是方法:

I want to test if my state is updated after an API call in my component. I have a method lets say method1() and in that method, it calls fetch and sets the state to the results. Here is the method:

method1 = () => {
if (this.state.state1 !== "") {
  fetch('api')
  .then((resp) => resp.json())
  .then((data) => {
    this.setState({ state2: data });
  })
  .catch((error) => {
    console.log(error);
  });
}

}

在我的测试文件中,我已经使用 fetch-mock 模拟了API,下面是尝试测试此API的测试:

In my test file I already mocked the API with fetch-mock and here is the test trying to test this:

it('updates the state after the api call', () => {
  const instance = component.instance();
  instance.method1();
  expect(component.state('state2')).toBe(MOCK_DATA);
});

我的 MOCK_DATA 与模拟一起定义在 beforeEach()

My MOCK_DATA is defined along with the mock fetches and component (shallow) in beforeEach()

中获取内容和组件(浅)时,运行 state2 仍处于初始状态( [] ),但我希望它是一个填充数组。

When I run this, state2 is still in its initial state ([]), but I'm expecting it to be a populated array.

我也尝试使测试异步并使用 await ,但得到的结果相同。

I also tried making the test async and using await but I am getting the same results.

任何帮助将不胜感激!谢谢!

Any help would be appreciated! Thanks!

推荐答案

这是不使用 fetch-mock 的解决方案。您可以自己手动模拟获取

Here is a solution without using fetch-mock. You can mock fetch manually by yourself.

index.tsx

import React, { Component } from 'react';
import fetch from 'node-fetch';

interface ISomeComponentState {
  state1: string;
  state2: string;
}

export class SomeComponent extends Component<any, ISomeComponentState> {
  constructor(props) {
    super(props);
    this.state = {
      state1: 'jest',
      state2: ''
    };
  }

  public async method1() {
    if (this.state.state1 !== '') {
      await fetch('api')
        .then(resp => resp.json())
        .then(data => {
          this.setState({ state2: data });
        })
        .catch(error => {
          console.log(error);
        });
    }
  }

  public render() {
    return <div>test</div>;
  }
}

单元测试, index.spec.tsx

import React from 'react';
import { SomeComponent } from './';
import { shallow, ShallowWrapper } from 'enzyme';
import fetch from 'node-fetch';

const { Response } = jest.requireActual('node-fetch');

jest.mock('node-fetch');

describe('SomeComponent', () => {
  let component: ShallowWrapper;
  beforeEach(() => {
    component = shallow(<SomeComponent></SomeComponent>);
  });

  it('snapshot', () => {
    expect(component).toMatchSnapshot();
  });

  it('should not fetch api', async () => {
    const mockedState = { state1: '', state2: '' };
    component.setState(mockedState);
    expect(component.state()).toEqual(mockedState);
    await (component.instance() as SomeComponent).method1();
    expect(fetch).not.toBeCalled();
    expect(component.state()).toEqual(mockedState);
  });

  it('should fetch api correctly', async () => {
    (fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce(new Response(JSON.stringify('mocked data')));
    expect(component.state()).toEqual({ state1: 'jest', state2: '' });
    await (component.instance() as SomeComponent).method1();
    expect(fetch).toBeCalledWith('api');
    expect(component.state()).toEqual({ state1: 'jest', state2: 'mocked data' });
  });

  it('will fetch error', async () => {
    const mockedError = new Error('some error');
    const consoleLogSpyOn = jest.spyOn(console, 'log');
    (fetch as jest.MockedFunction<typeof fetch>).mockRejectedValueOnce(mockedError);
    await (component.instance() as SomeComponent).method1();
    expect(fetch).toBeCalledWith('api');
    expect(consoleLogSpyOn).toBeCalledWith(mockedError);
    expect(component.state()).toEqual({ state1: 'jest', state2: '' });
  });
});

具有100%覆盖率的单元测试结果:

Unit test result with 100% coverage:

 PASS  src/stackoverflow/52899150/index.spec.tsx
  SomeComponent
    ✓ snapshot (20ms)
    ✓ should not fetch api (5ms)
    ✓ should fetch api correctly (6ms)
    ✓ will fetch error (11ms)

  console.log node_modules/jest-mock/build/index.js:860
    Error: some error
        at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:38:25)
        at step (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:32:23)
        at Object.next (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:13:53)
        at /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:7:71
        at new Promise (<anonymous>)
        at Object.<anonymous>.__awaiter (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:3:12)
        at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/52899150/index.spec.tsx:37:26)
        at Object.asyncJestTest (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
        at resolve (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
        at new Promise (<anonymous>)
        at mapper (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
        at promise.then (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:73:41)
        at process._tickCallback (internal/process/next_tick.js:68:7)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   1 passed, 1 total
Time:        4.697s

以下是完整的演示: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52899150

这篇关于在React中测试API调用-状态未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆