Как издеваться над импортом модуля 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
все время. Меня это беспокоит, но пока это моя лучшая идея.