Как издеваться над импортом модуля ES6?

У меня есть следующие модули ES6:

network.js

export function getDataFromServer() {
  return ...
}

widget.js

import { getDataFromServer } from 'network.js';

export class Widget() {
  constructor() {
    getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }

  render() {
    ...
  }
}

Я ищу способ протестировать виджет с помощью ложного экземпляраgetDataFromServer, Если бы я использовал отдельный<script>s вместо модулей ES6, как в Karma, я мог бы написать свой тест следующим образом:

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(window, "getDataFromServer").andReturn("mockData")
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

Однако, если я тестирую модули ES6 индивидуально вне браузера (как с Mocha + babel), я бы написал что-то вроде:

import { Widget } from 'widget.js';

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(?????) // How to mock?
    .andReturn("mockData")
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

Хорошо но теперьgetDataFromServer недоступно вwindow (ну нетwindow вообще), и я не знаю, как ввести материал напрямую вwidget.jsСфера охвата.

Так куда мне идти отсюда?Есть ли способ получить доступ к объемуwidget.jsили хотя бы заменить его импорт своим собственным кодом?Если нет, как я могу сделатьWidget тестируемый?Материал, который я рассмотрел:а. Ручное внедрение зависимостей.

Удалить весь импорт изwidget.js и ожидаем, что звонящий предоставит депс.

export class Widget() {
  constructor(deps) {
    deps.getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }
}

Мне очень неудобно портить публичный интерфейс Widget и показывать детали реализации. Нет идти

б. Выставьте импорт, чтобы позволить насмехаться над ними.

Что-то вроде:

import { getDataFromServer } from 'network.js';

export let deps = {
  getDataFromServer
};

export class Widget() {
  constructor() {
    deps.getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }
}

затем:

import { Widget, deps } from 'widget.js';

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(deps.getDataFromServer)  // !
      .andReturn("mockData");
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

Это менее инвазивно, но требует от меня написания большого количества шаблонов для каждого модуля, и есть риск, что я буду использоватьgetDataFromServer вместоdeps.getDataFromServer все время. Меня это беспокоит, но пока это моя лучшая идея.

Ответы на вопрос(5)

Ваш ответ на вопрос