Ich habe einige eng gekoppelten Legacy-Code, den ich mit Tests abdecken möchte. Manchmal ist es wichtig sicherzustellen, dass eine verspottete Methode vor einer anderen aufgerufen wird. Ein vereinfachtes Beispiel:Wie zu testen, dass eine Funktion vor einem anderen aufgerufen wird
function PageManager(page) {
this.page = page;
}
PageManager.prototype.openSettings = function(){
this.page.open();
this.page.setTitle("Settings");
};
Im Test kann ich, dass beide überprüfen open()
und setTitle()
genannt werden:
describe("PageManager.openSettings()", function() {
beforeEach(function() {
this.page = jasmine.createSpyObj("MockPage", ["open", "setTitle"]);
this.manager = new PageManager(this.page);
this.manager.openSettings();
});
it("opens page", function() {
expect(this.page.open).toHaveBeenCalledWith();
});
it("sets page title to 'Settings'", function() {
expect(this.page.setTitle).toHaveBeenCalledWith("Settings");
});
});
Aber setTitle()
funktioniert nur nach dem ersten open()
aufrufen. Ich möchte überprüfen, dass zuerst page.open()
aufgerufen wird, gefolgt von setTitle()
. Ich möchte so etwas schreiben:
it("opens page before setting title", function() {
expect(this.page.open).toHaveBeenCalledBefore(this.page.setTitle);
});
Aber Jasmin scheint nicht in eine solche Funktionalität gebaut haben
ich so etwas wie dieses zerhacken kann.
beforeEach(function() {
this.page = jasmine.createSpyObj("MockPage", ["open", "setTitle"]);
this.manager = new PageManager(this.page);
// track the order of methods called
this.calls = [];
this.page.open.and.callFake(function() {
this.calls.push("open");
}.bind(this));
this.page.setTitle.and.callFake(function() {
this.calls.push("setTitle");
}.bind(this));
this.manager.openSettings();
});
it("opens page before setting title", function() {
expect(this.calls).toEqual(["open", "setTitle"]);
});
Diese funktioniert, aber ich frage mich, ob es einen einfacheren Weg gibt, dies zu erreichen. Oder eine nette Möglichkeit, dies zu verallgemeinern, damit ich diesen Code nicht in anderen Tests kopieren muss.
PS. Natürlich ist der richtige Weg, den Code umzuformen, um diese Art der zeitlichen Kopplung zu eliminieren. Es ist jedoch nicht immer möglich, z.B. wenn Schnittstellen mit Bibliotheken von Drittanbietern hergestellt werden. Wie auch immer ... Ich möchte zuerst den vorhandenen Code mit Tests abdecken und ihn so wenig wie möglich modifizieren, bevor ich weitere Refactorings durchführe.
Gibt es etwas, das Sie geltend machen können, außer dass 'open' aufgerufen wurde? Wie einige DOM-Knoten ändern oder andere "globale" Daten? –
Nein. Der springende Punkt ist, dass ich mich darüber lustig mache - ich möchte nicht, dass das eigentliche 'open' aufgerufen wird, besonders weil es einen globalen Zustand beeinflussen könnte. –
Mögliches Duplikat von [Gibt es eine Möglichkeit, die Reihenfolge der Spionagedurchführungen mit Jasmine zu überprüfen?] (Https://stackoverflow.com/questions/20055781/is-there-a-way-to-verify-the-order-of -spy-executions-with-jasmine) – carpeliam