Ren*_*soo 7 javascript unit-testing jasmine
我有一些紧密耦合的遗留代码,我想用测试来覆盖.有时确保在另一个方法之前调用一个模拟方法很重要.一个简化的例子:
function PageManager(page) {
this.page = page;
}
PageManager.prototype.openSettings = function(){
this.page.open();
this.page.setTitle("Settings");
};
Run Code Online (Sandbox Code Playgroud)
在测试中我可以检查两者open()并被setTitle()调用:
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");
});
});
Run Code Online (Sandbox Code Playgroud)
但setTitle()只有在第一次打电话后才能工作open().我想先检查一下page.open(),然后是setTitle().我想写这样的东西:
it("opens page before setting title", function() {
expect(this.page.open).toHaveBeenCalledBefore(this.page.setTitle);
});
Run Code Online (Sandbox Code Playgroud)
但Jasmine似乎并没有内置这样的功能.
我可以破解这样的东西:
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"]);
});
Run Code Online (Sandbox Code Playgroud)
这有效,但我想知道是否有一些更简单的方法来实现这一点.或者一些很好的方法来概括这一点,所以我不需要在其他测试中复制此代码.
PS.当然,正确的方法是重构代码以消除这种时间耦合.但是,例如,当与第三方库连接时,可能并非总是可能.无论如何...我想首先用测试覆盖现有代码,尽可能少地修改它,然后再深入研究进一步的重构.
我想写这样的东西:
Run Code Online (Sandbox Code Playgroud)it("opens page before setting title", function() { expect(this.page.open).toHaveBeenCalledBefore(this.page.setTitle); });但是 Jasmine 似乎没有内置这样的功能。
看起来 Jasmine 的人看到了这个帖子,因为这个功能存在。我不确定它已经存在多久了——他们所有回到 2.6 的 API 文档都提到了它,尽管他们存档的旧样式文档都没有提到它。
toHaveBeenCalledBefore(
expected)
期望实际值(一个Spy)在另一个Spy之前被调用。参数:
Run Code Online (Sandbox Code Playgroud)Name Type Description expected Spy Spy that should have been called after the actual Spy.
您的示例的失败看起来像Expected spy open to have been called before spy setTitle.
尝试这个:
it("setTitle is invoked after open", function() {
var orderCop = jasmine.createSpy('orderCop');
this.page.open = jasmine.createSpy('openSpy').and.callFake(function() {
orderCop('fisrtInvoke');
});
this.page.setTitle = jasmine.createSpy('setTitleSpy').and.callFake(function() {
orderCop('secondInvoke');
});
this.manager.openSettings();
expect(orderCop.calls.count()).toBe(2);
expect(orderCop.calls.first().args[0]).toBe('firstInvoke');
expect(orderCop.calls.mostRecent().args[0]).toBe('secondInvoke');
}
Run Code Online (Sandbox Code Playgroud)
编辑:我刚刚意识到我的原始答案实际上与您在问题中提到的hack相同,但是在设置间谍方面有更多开销。用“ hack”方式做起来可能更简单:
it("setTitle is invoked after open", function() {
var orderCop = []
this.page.open = jasmine.createSpy('openSpy').and.callFake(function() {
orderCop.push('fisrtInvoke');
});
this.page.setTitle = jasmine.createSpy('setTitleSpy').and.callFake(function() {
orderCop.push('secondInvoke');
});
this.manager.openSettings();
expect(orderCop.length).toBe(2);
expect(orderCop[0]).toBe('firstInvoke');
expect(orderCop[1]).toBe('secondInvoke');
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1988 次 |
| 最近记录: |