Aşağıdaki ES6 modüllerine sahibim:
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'ı sahte bir örnekle test etmenin bir yolunu arıyorum getDataFromServer. <script>Karma gibi ES6 modülleri yerine ayrı s kullandıysam, testimi şöyle yazabilirdim:
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();
});
});
Ancak, ES6 modüllerini tek tek bir tarayıcının dışında test edersem (Mocha + babel gibi), şöyle bir şey yazardım:
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();
});
});
Tamam, ama şu anda getDataFromServermevcut değil window(iyi, hiç yok window) ve bir şeyleri doğrudan widget.jskendi kapsamına enjekte etmenin bir yolunu bilmiyorum .
Peki buradan nereye gideceğim?
- İçe aktarma kapsamına erişmenin
widget.jsveya en azından ithalatını kendi kodumla değiştirmenin bir yolu var mı ? - Değilse, nasıl
Widgettest edilebilir yapabilirim ?
Düşündüğüm şeyler:
a. Manuel bağımlılık enjeksiyonu.
Tüm ithalatları kaldırın widget.jsve arayanın depsi sağlamasını bekleyin.
export class Widget() {
constructor(deps) {
deps.getDataFromServer("dataForWidget")
.then(data => this.render(data));
}
}
Widget'ın genel arayüzünü bu şekilde karıştırmak ve uygulama ayrıntılarını ortaya çıkarmaktan çok rahatsızım. Gitme.
b. İthalatları alay konusu yapmak için açıkta bırakın
Gibi bir şey:
import { getDataFromServer } from 'network.js';
export let deps = {
getDataFromServer
};
export class Widget() {
constructor() {
deps.getDataFromServer("dataForWidget")
.then(data => this.render(data));
}
}
sonra:
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();
});
});
Bu daha az invazivdir, ancak her modül için çok sayıda kaynatma plakası yazmamı gerektirir ve hala her zaman getDataFromServeryerine kullanma riskim var deps.getDataFromServer. Bu konuda huzursuzum ama şimdiye kadarki en iyi fikrim bu.
createSpy ( github.com/jasmine/jasmine/blob/… ) işlevini 'network.js' modülünden DataFromServer almak için içe aktarılmış bir referansla kullanmaya çalışacağım . Böylece, widget'ın test dosyasında getDataFromServer'ı içe aktarırsınız ve sonralet spy = createSpy('getDataFromServer', getDataFromServer)
spyOniçe aktarılan bu nesne üzerinde olabilirsiniz network.js. Her zaman aynı nesneye referanstır.
Widgetgenel arayüzünü nasıl bozduğunu gerçekten anlamıyorum ? olmadanWidget berbat . Bağımlılığı neden açık hale getirmiyorsun? deps