我有以下 ES6单元:
export function getDataFromServer() {
return ...
}
import { getDataFromServer } from 'network.js';
export class Widget() {
constructor() {
getDataFromServer("dataForWidget")
.then(data => this.render(data));
}
render() {
...
}
}
我正在寻找一种用 getDataFromServer
的模拟实例测试 Widget 的方法。如果我使用单独的 <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模块(比如使用 摩卡 + 巴别塔) ,我会这样写:
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();
});
});
好吧,但是现在 window
中没有 getDataFromServer
(好吧,根本就没有 window
) ,而且我不知道一种方法可以直接把东西注入到 widget.js
自己的作用域中。
widget.js
的作用域,或者至少用我自己的代码替换它的导入?Widget
可测试?从 widget.js
删除所有导入,并期望调用方提供 deps。
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
的风险。我对此感到不安,但这是目前为止我最好的主意。