Как проверить параметры контекстной функции, вызываемой в компонентной функции?

#reactjs #unit-testing #jestjs #enzyme #react-context

Вопрос:

Я видел несколько примеров того, как имитировать контекст и как имитировать вызов конкретной функции компонента, но я не нашел ни одного, который выполнял бы и то, и другое одновременно. В большинстве случаев для правильного насмешливого контекста рекомендуется использовать mount() , но тогда это не дает мне доступа к возвращаемому экземпляру, из shallow(<MyComponent>).instance() которого я затем использовал бы вызов функции. Это пример ситуации, которую я пытаюсь проверить:

 class MyComponent extends Component {
    static contextType = MyContext
    constructor(props) {
        super(props);
        this.myFunction = this.myFunction.bind(this);
    }
    myFunction() {
        this.context.otherFunction('shouldBecorrectValue');
    }
}
 

В идеале я хотел бы иметь возможность сделать это без изменения тестируемого кода.

Ответ №1:

Существует .instance() => ReactComponent> метод для оболочки, возвращаемой mount . Работает только для компонента класса.

Возвращает экземпляр базового класса узла оболочки с одним узлом.

index.tsx :

 import React, { Component } from 'react';

const MyContext = React.createContext({
  otherFunction: (value) => {
    console.log(value);
  },
});

export class MyComponent extends Component {
  static contextType = MyContext;
  myFunction() {
    this.context.otherFunction('shouldBecorrectValue');
  }
  render() {
    return <div>my component</div>;
  }
}
 

index.test.tsx :

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

describe('69127076', () => {
  test('should pass', () => {
    const logSpy = jest.spyOn(console, 'log');
    const wrapper = mount(<MyComponent />);
    wrapper.instance()['myFunction']();
    expect(logSpy).toBeCalledWith('shouldBecorrectValue');
    logSpy.mockRestore();
  });
});
 

результат теста:

  PASS  examples/69127076/index.test.tsx (10.228 s)
  69127076
    ✓ should pass (47 ms)

  console.log
    shouldBecorrectValue

      at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)

-----------|---------|----------|---------|---------|-------------------
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:       1 passed, 1 total
Snapshots:   0 total
Time:        10.804 s
 

версии пакетов:

 "enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"react": "^16.14.0",
"react-dom": "^16.14.0",
 

Комментарии:

1. Кроме того, ваш пример не показывает, как вы издеваетесь над контекстом в тесте. В настоящее время я занимаюсь этим: context = {otherFunction: jest.fn()} и mount(<MyComponent>, {context}).instance() . Нужно ли мне также использовать React.createContext(context) ?

2. Извините, я имел в виду, что могу создать экземпляр, но всякий раз, когда я это делаю, мне кажется, что это приводит thrown: undefined к ошибке при тестировании. Поэтому я предположил, что был какой-то другой шаг, который я пропустил.