如何用 jest 模拟和测试链式函数?

How do I mock and test chained function with jest?

我的组件 useEffect 挂钩中有这个函数链。 我将 response/data 设置为我的组件状态,以便我可以在我的组件中呈现数据。

client
  .items()
  .type("client")
  .toObservable()
  .subscribe(response => {
    setState(response)
  })

如何模拟此函数并在我的测试中呈现组件之前调用它?我正在使用 testing-library/react.

响应是 {items: [{},...]}, somethingElse: {}

您可以使用 mockFn.mockReturnThis() 来执行此操作。

client.ts,模拟真实的第三方模块

const client = {
  items: () => {
    return client;
  },
  type: (name: string) => {
    return client;
  },
  toObservable: () => {
    return client;
  },
  subscribe: handler => {
    handler();
    return client;
  }
};

export { client };

在 React 组件中使用 client.ts 模块:

class Component {
  private props;
  constructor(props) {
    this.props = props;
  }
  public componentDidMount() {
    this.props.client
      .items()
      .type('client')
      .toObservable()
      .subscribe(response => {
        this.setState(response);
      });
  }
  private setState(state) {
    console.log(state);
  }
}

export { Component };

单元测试,真实client.ts模块的模拟链方法,将模拟的client模块注入到您的组件中。

import { Component } from './';

const mockClient = {
  items: jest.fn().mockReturnThis(),
  type: jest.fn().mockReturnThis(),
  toObservable: jest.fn().mockReturnThis(),
  subscribe: jest.fn().mockReturnThis()
};

const mockProps = {
  client: mockClient
};

const component = new Component(mockProps);

describe('Component', () => {
  describe('#componentDidMount', () => {
    it('should mount the component and set state correctly', () => {
      const mockedResponse = { items: [{}], somethingElse: {} };
      mockClient.subscribe.mockImplementationOnce(handler => handler(mockedResponse));
      // tslint:disable-next-line: no-string-literal
      component['setState'] = jest.fn();
      component.componentDidMount();
      expect(mockClient.items().type).toBeCalledWith('client');
      // tslint:disable-next-line: no-string-literal
      expect(component['setState']).toBeCalledWith(mockedResponse);
    });
  });
});

单元测试结果:

 PASS  src/mock-function/57719741/index.spec.ts
  Component
    #componentDidMount
      ✓ should mount the component and set state correctly (6ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.542s, estimated 2s