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 getDataFromServer
mevcut değil window
(iyi, hiç yok window
) ve bir şeyleri doğrudan widget.js
kendi kapsamına enjekte etmenin bir yolunu bilmiyorum .
Peki buradan nereye gideceğim?
- İçe aktarma kapsamına erişmenin
widget.js
veya en azından ithalatını kendi kodumla değiştirmenin bir yolu var mı ? - Değilse, nasıl
Widget
test edilebilir yapabilirim ?
Düşündüğüm şeyler:
a. Manuel bağımlılık enjeksiyonu.
Tüm ithalatları kaldırın widget.js
ve 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 getDataFromServer
yerine 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)
spyOn
içe aktarılan bu nesne üzerinde olabilirsiniz network.js
. Her zaman aynı nesneye referanstır.
Widget
genel arayüzünü nasıl bozduğunu gerçekten anlamıyorum ? olmadanWidget
berbat . Bağımlılığı neden açık hale getirmiyorsun? deps