При тестировании я продолжал вспоминать шаблон для имитации библиотечных функций, особенно когда мне нужно иметь дело с другим типом импорта, а также с другим компилятором, таким как машинописный текст. Итак, я хотел бы резюмировать основной способ здесь.

Макет библиотеки

Скажем, у вас есть библиотека, экспортирующая пару служебных функций:

export function concat(a, b) {
  return a + b
}

export default function sum(a, b) {
  return a + b;
}

Чтобы протестировать вышеуказанные функции, мы можем использовать Jest:

import sum, { concat } from '../lib';

describe('lib', () => {
  it('sum', () => {
    expect(sum(1, 1)).toBe(2);
  });

  it('concat', () => {
    expect(concat('Hello', 'World')).toBe('HelloWorld');
  });
});

Это модульное тестирование 101. Довольно часто нам нужно смоделировать некоторые функции, чтобы мы хотели пропустить их реальную реализацию и сразу перейти к смоделированному результату. В этом случае мы просто применяем jest.mock к файлу библиотеки:

import sum, { concat } from '../lib';

jest.mock('../lib');

describe('lib', () => {
  it('sum', () => {
    sum.mockImplementation(() => 2);
    expect(sum()).toBe(2);
  });

  it('concat', () => {
    concat.mockImplementation(() => 'a');
    expect(concat()).toBe('a');
  });
});

Хорошая вещь в jest.mock заключается в том, что он работает не только для частичного импорта, такого как concat , но также работает для импорта по умолчанию sum прямо из коробки. После этого все функции из библиотеки конвертируются в jest.fn() объект. Поэтому все ваши насмешливые упражнения будут применяться соответственно.

Только когда вы не хотите издеваться над всей библиотекой или хотите установить какое-то значение по умолчанию для одной из функций, вам нужно кодировать jest.mock:

jest.mock('../sum', () => {
  return {
    __esModule: true,
    default: jest.fn(() => 4)
  };
});

Вы можете найти больше в разделе документация Jest Mocking Partials, где приводится больше примеров работы с различными ситуациями.

Машинопись

Жизнь не так проста. Когда я перехожу на Typescript, вдруг что-то перестает работать, поэтому люди придумывают всевозможные способы борьбы с этим. На самом деле все, что нам не хватает, это набор типов.

import { concat } from '../lib';

jest.mock('../lib');

describe('lib', () => {
  it('concat', () => {
    (concat as jest.Mock).mockImplementation(() => 'abc');
    expect(concat('a', 'b')).toBe('abc');
  });
});

Без приведения concat по-прежнему считается обычной функцией в Typescript. Поэтому нам нужно привести его к jest.Mock. Из этого Stackoverflow правильным способом может быть преобразование его в MockedFunction:

import { concat } from '../lib';

jest.mock('../lib');

const mockedConcat = concat as jest.MockedFunction<typeof concat>;

describe('lib', () => {
  it('concat', () => {
    mockedConcat.mockImplementation(() => 'abc');
    expect(concat('a', 'b')).toBe('abc');
  });
});

В той же ветке кто-то упомянул еще один хороший простой способ победить его через spyOn :

import * as _ from '../lib';

jest.mock('../lib');
const concat = jest.spyOn(_, 'concat');

describe('lib', () => {
  it('concat', () => {
    concat.mockImplementation(() => 'abc');
    expect(_.concat('a', 'b')).toBe('abc');
  });
});

Единственная загвоздка в том, что вам нужно иметь доступ ко всей библиотеке, такой как * as _ , потому что шпион может быть применен только к родительскому object.

Краткое содержание

Я надеюсь, что у меня будет лучшая жизнь в фиктивных модулях с вышеуказанными знаниями. В основном делайте jest.mock и, если тип отсутствует, приведите его, прежде чем продолжить по-старому. Вот и все.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.