Jest 监视组件的 属性 方法

Jest spy on component's property method

我正在尝试测试是否在 componentDidMount 调用的 init 方法中添加了一个事件,但是只有在 "true" 中设置了组件的属性时才会添加该事件,所以我想监视 addEventHandler 方法并调用 "toBeCalledWith('eventName')" 所以我有这样的东西:

export interface IMyComponentProps{
    flag?: boolean;
}

export class MyComponent extends Component<IMyComponentProps> {
    private myProperty: HTMLElement;

    public componentDidMount() {
        this.init();
    }

    private init() {
        if (this.props.flag) {
            this.myProperty.addEventListener("event", arg2, arg3);
        }
    }
}

然后我的测试看起来像这样:

test("Test 1", () => {
   const spyInit = jest.spyOn(MyComponent.prototype, "init");
   wrapper = mount(
      <MyComponent />
   );

   expect(spyInit).toBeCalled();
})

但是上面的测试不包括是否调用了 addEventListener 所以我尝试了不同的方法,比如下面的方法,但没有成功:

const spyAddListener = jest.spyOn(MyComponent.prototype, "myProperty.addEventHandler"); 
const spyAddListener = jest.spyOn(MyComponent.instance().myProperty, "addEventHandler"); 
const spyAddListener = jest.spyOn(MyComponent.prototype.myProperty, "addEventHandler");

有什么建议吗?

您需要将 flag 道具传递给组件。例如

index.ts:

import { Component } from 'react';

export interface IMyComponentProps {
  flag?: boolean;
}

export class MyComponent extends Component<IMyComponentProps> {
  private myProperty!: HTMLElement;

  public componentDidMount() {
    this.init();
  }
  public render() {
    return null;
  }

  private init() {
    if (this.props.flag) {
      this.myProperty.addEventListener('event', () => null, false);
    }
  }
}

index.test.tsx:

import { MyComponent } from './';
import { mount } from 'enzyme';
import React from 'react';

describe('60714899', () => {
  it('should add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={true} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).toBeCalledWith('event', expect.any(Function), false);
  });

  it('should NOT add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={false} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).not.toBeCalled();
  });
});

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

 PASS  Whosebug/60714899/index.test.tsx
  60714899
    ✓ should add event listener (42ms)
    ✓ should NOT add event listener (2ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   92.31 |      100 |      80 |     100 |                   
 index.tsx |   92.31 |      100 |      80 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.77s, estimated 10s

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/Whosebug/60714899

没有完全回答这个问题,但是从 jasmine 迁移到 jest 的人可能会发现这很有用。

jest.spyOn(component, 'propertyName', 'get').mockReturnValue(...);

这相当于 jasmine 的 spyOnProperty:

jasmine.spyOnProperty(component, 'propertyName').and.returnValue(...);