У меня есть следующие модули 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() {
    ...
  }
}
Я ищу способ проверить Widget с помощью mock-экземпляра getDataFromServer. Если бы я использовал отдельные <script> вместо модулей 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или, по крайней мере, заменить его импорт моим собственным кодом?
-   Если нет, как я могу сделать Widgettestable?
Материал, который я рассмотрел:
а. Ручная инъекция зависимостей.
Удалите все импорт из 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. Я беспокоюсь об этом, но это моя лучшая идея.
