Сброс узла модуля в Jest - PullRequest
2 голосов
/ 07 июля 2019

У меня есть приложение Node.js, где index.js имеет разные экспорты для Unix-подобных и платформ Windows.

import os from "os";

function throwNotSupportedError() {
  throw new Error("Platform not supported.");
}

console.log(os.platform());

switch (os.platform()) {
  case "darwin":
  case "linux":
    module.exports = {
      foo: require("./unix/foo"),
      bar: require("./unix/bar")
    };
    break;
  case "win32":
    module.exports = {
      foo: require("./win32/foo"),
      bar: require("./win32/bar")
    };
    break;
  default:
    throwNotSupportedError();
}

И я пытаюсь покрыть этот файл модульными тестами, которые выглядят так:

import os from "os";

jest.mock("os");

describe("Linux platform", () => {
  test("has `foo` and `bar` methods on Linux platform", () => {
    os.platform.mockImplementation(() => "linux");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

describe("Windows platform", () => {
  test("has `foo` and `bar` methods on Windows platform", () => {
    os.platform.mockImplementation(() => "win32");

    const app = require("../src");
    expect(app.foo).toBeTruthy();
    expect(app.bar).toBeTruthy();
  });
});

Дело в том, что os.platform.mockImplementation(() => "win32"); работает, но console.log(os.platform()); по-прежнему показывает linux, даже если я импортирую приложение в каждом тестовом примере const app = require("../src");.

Где моя ошибкаи как это решить?

Ответы [ 3 ]

1 голос
/ 13 июля 2019

Ответ Кханга о jest.resetModules() указывает на правильное направление.Я хотел бы добавить, что когда вы сбрасываете модули, ссылки на любой предыдущий импорт будут «игнорироваться» (после сброса создается новый экземпляр).Другими словами, import os from "os"; в верхней части теста больше не будет использоваться после сброса модуля.

Решение

В дополнение к jest.resetModules() вам необходимо повторно импортировать (или в этом случае повторно потребовать) модуль os внутри теста, который вы собираетесь выполнить.Таким образом, os.platform.mockImplementation(() => "win32"); будет применен к последнему экземпляру макета модуля.Оба ваших теста должны быть структурированы таким образом:

test("has `foo` and `bar` methods on Windows platform", () => {
  const os = require('os');
  os.platform.mockImplementation(() => "win32");

  const app = require("./os-test");
  expect(app.foo).toBeTruthy();
  expect(app.bar).toBeTruthy();
});

Возможно, вы захотите использовать beforeEach вместо afterEach, чтобы гарантировать, что модуль os чист перед тестом.Jest должен изолировать каждый тестовый файл, но лучше, чем потом сожалеть?Наконец, вы бы хотели, чтобы beforeEach запускался до всех тестов, а не только внутри «платформы Windows» describe.Для этого вы можете переместить его в корень файла или обернуть два describe в дополнительный describe, например,

jest.mock("os");

describe('Platform specific module', () => {
  beforeEach(() => {
    jest.resetModules();
  });

  describe("Linux platform", () => {
    test("has `foo` and `bar` methods on Linux platform", () => {
      const os = require('os');
      os.platform.mockImplementation(() => "linux");
      ...

Надеюсь, это поможет!Насмешка, как правило, сложно, не только в шутку.

Ссылки

0 голосов
/ 10 июля 2019

Вам нужно будет использовать jest.resetModules() после каждого теста, чтобы очистить кэш модуля:

describe("Windows platform", () => {
    afterEach(() => {
        jest.resetModules();
    })

    //...
})
0 голосов
/ 09 июля 2019

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

Кстати, это всего лишь непроверенная теория, прочитав учебник по Jest mocks .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...