Javascript 使用Jasmine模拟多个方法调用
我正在尝试用JavaScript编写一个测试,我正在测试的方法会调用两个方法(model.expandChildren()和view.update();) 我曾尝试使用Jasmine specs来编写对spyOn的view和model函数的测试,但似乎在给定的测试中只能有一个spy。似乎我在这里遗漏了一些重要的东西,应该有一种方法可以使用spies模拟多个方法调用,因为我的函数需要进行这两个调用 我希望我的规范能够按照下面的方式运行,但它目前只通过第一个测试(第一个spy按预期运行),第二个测试失败,因为Jasmine正在尝试运行实际的函数,而不是spied函数:Javascript 使用Jasmine模拟多个方法调用,javascript,unit-testing,jasmine,Javascript,Unit Testing,Jasmine,我正在尝试用JavaScript编写一个测试,我正在测试的方法会调用两个方法(model.expandChildren()和view.update();) 我曾尝试使用Jasmine specs来编写对spyOn的view和model函数的测试,但似乎在给定的测试中只能有一个spy。似乎我在这里遗漏了一些重要的东西,应该有一种方法可以使用spies模拟多个方法调用,因为我的函数需要进行这两个调用 我希望我的规范能够按照下面的方式运行,但它目前只通过第一个测试(第一个spy按预期运行),第二个测试
var model = GRAPH.model;
var view = GRAPH.view;
var app = RV.graph;
describe('#expandChildren', function() {
beforeEach(function() {
// first spy, all good
spyOn(model, 'expandChildren').and.callFake(function() {
return new Promise(function(resolve) {
resolve(testResponse);
});
});
// second spy doesn't work because Jasmine only allows 1
spyOn(view, 'update');
app.expandChildren();
});
// passing test
it('calls model.expandChildren', function() {
expect(model.expandChildren).toHaveBeenCalled();
});
// failing test that runs the REAL view.update method
it('calls view.update', function() {
expect(view.update).toHaveBeenCalled();
});
});
有没有办法用Jasmine做到这一点?请记住,您使用的是异步调用。第一个调用是同步的,因此会被记录,但第二个调用只会在稍后发生。当事情发生时,给自己一些控制权。我通常使用这样的模式:
describe('#expandChildren', function() {
var resolver;
it('calls model.expandChildren', function(done) {
spyOn(model, 'expandChildren').and.callFake(function() {
return new Promise(function(resolve) {
resolver = resolve;
});
});
spyOn(view, 'update');
app.expandChildren();
expect(model.expandChildren).toHaveBeenCalled();
expect(view.update).not.toHaveBeenCalled();
resolver();
done();
expect(view.update).toHaveBeenCalled();
});
});
这样,只有在承诺得到解决并且调用了
done()
之后,规范才会运行。解决肯定是另一个问题,但即使是done()
我的第二次测试仍然失败。我可能有误解,但我的印象是,每个描述块只能使用一个间谍,即使测试套件中有多个间谍。可以创建的间谍数量没有限制。无论如何,在创建时同步解决承诺可能还为时过早。我从未尝试过这种模式,但总是手工解决。通过这种方式,您可以额外测试异步代码,该代码只在稍后执行。见编辑后的答案。
describe('#expandChildren', function() {
var resolver;
it('calls model.expandChildren', function(done) {
spyOn(model, 'expandChildren').and.callFake(function() {
return new Promise(function(resolve) {
resolver = resolve;
});
});
spyOn(view, 'update');
app.expandChildren();
expect(model.expandChildren).toHaveBeenCalled();
expect(view.update).not.toHaveBeenCalled();
resolver();
done();
expect(view.update).toHaveBeenCalled();
});
});