До переезда в Jest мы использовали Karma с Mocha / Chai. У них нет встроенных функций имитации (насколько мне известно). Если вы разработчик C #, вы знаете все о различных фреймворках Mock (например, Moq) и хотите иметь возможность делать то же самое со своим TypeScript, верно? По крайней мере, я знаю. Я хочу изо всех сил следовать ТВЕРДЫМ принципам (о них я напишу позже в этом году).

Итак, поскольку в этих тестовых фреймворках нет макетов, нам пришлось использовать такие вещи, как Sinon или Proxyquire. Это выполнимо. Это действительно так. Но зачем вам эти дополнительные фреймворки и весь этот дополнительный код, когда уже есть тестовый раннер / фреймворк, в который все это встроено. И ... и он отлично работает с React, потому что он создан теми же ребятами (Facebook).

Enter Jest.

Jest - отличный фреймворк для тестирования с довольно хорошей готовой функциональностью. Во-первых, он распараллеливает ваши тесты, поэтому они будут работать быстрее. Выполнение сотен или тысяч тестов занимает всего пару минут. Думаю, когда мы это реализовали, это было примерно в половине случаев. В него встроены отличные имитации. Это замечательно для TypeScript, потому что вы можете имитировать весь импорт. Есть только одно предостережение; убедитесь, что макет находится перед компонентом, который импортирует импорт, который вы хотите имитировать.

Фермент

Прежде чем продолжить насмешку (в тестах), я должен поговорить о Enzyme (от Airbnb). Фермент - это находка. Это делает тестирование кода React намного лучше. Но нужно быть осторожным. Мы стараемся использовать неглубокий рендеринг, а не полный рендеринг DOM (монтирование). Почему? Потому что это намного быстрее, потому что вы не все визуализируете. Также потому, что вам не нужно тестировать дочерние компоненты в родительском компоненте. Я имею в виду, что вы бы не сделали этого на C #, так зачем вам делать это с Enzyme?

Ниже приведен пример того, как вы можете протестировать компонент. Даже не видя фактического кода компонента, вы можете получить представление о том, как этот компонент выглядит. У него есть класс с именем .my-class, в имени которого есть текст. Мы также можем видеть, что у него, вероятно, есть div-оболочка с классом .my-class-wrapper.

import * as React from 'react';
import { shallow } from 'enzyme';
import { MyComponent, MyComponentProps } from './MyComponent';
describe('<MyComponent />', () => {
const initialProps: MyComponentProps = {
        name: 'John',
    };
test('Should display name correctly', () => {
        const props  = {
            ...initialProps,
        };
        const myComponent = shallow(<MyComponent {...props} />);
expect(myComponent).toMatchSnapshot();
        expect(myComponent.find('.my-class').at(0).text()).toBe(props.name);
        expect(myComponent.prop('className')).toBe('my-class-wrapper');
    });
});

Издевательство

Иногда у вас есть сложные компоненты с зависимостями, о которых вы не хотите беспокоиться. Возможно, например, вы решите использовать Google Maps, которые имеют внешнюю зависимость в вашем SPA. Он выполняет сетевой вызов и каждый раз дает сбой на вашем сервере сборки, у которого нет доступа в Интернет. У вас может быть что-то еще безумное. Кто знает? В любом случае, дело в том, что, возможно, вы не хотите, чтобы эта загрузка во время тестов. Вы можете имитировать свои вызовы API или что-нибудь еще.

import * as React from 'react';
import { shallow } from 'enzyme';
import { IMyApi } from './api';
const mockOnLoadFn = jest.fn();
const MyApi = jest.fn<IMyApi>((): IMyApi => ({
    getMyName: mockOnLoadFn,
}));
jest.mock('./api', () => ({
    MyApi,
}));
import { MyComponent, MyComponentProps } from './MyComponent';
describe('<MyComponent />', () => {
const initialProps: MyComponentProps = {
        name: 'John',
    };
test('Should display name correctly', () => {
        const props  = {
            ...initialProps,
        };
        const myComponent = shallow(<MyComponent {...props} />);
        myComponent.instance().componentDidMount();
expect(mockOnLoadFn).toHaveBeenCalledTimes(1);
    });
});

Из моего теста выше вы можете сказать, что, вероятно, во время componentDidMount getMyName в IMyApi вызывается один раз. Это не вызовет фактический API. Над ним красиво шутят, и его легко протестировать. Я знаю, что вызов экземпляра компонента - не лучший вариант, но если вы не хотите монтировать компонент, это лучший способ сделать это.

Вы даже можете вернуть значение из макета. Наверное, лучше посмотреть документацию Jest, чем мне трепаться об этом. ЕСЛИ ... если я не получу еще несколько запросов о насмешках в тестах и ​​т. Д.

Резюме

Используйте Jest, чтобы проверить свой код React. Используйте Enzyme вместе с React. Мокинг / заглушка хороши там, где это возможно.

Первоначально опубликовано на www.alexaitken.nz 12 февраля 2018 г.