[英]Jasmine test using .toHaveBeenCalledWith fails for sign-up form
The single page application I am working on has a login view with two forms: a sign-in form and a sign-up form. 我正在处理的单页面应用程序有一个登录视图,有两种形式:登录表单和注册表单。 The following spec describes tests for these forms.
以下规范描述了这些表单的测试。 I am using Jasmine-jQuery 1.4.2.
我正在使用Jasmine-jQuery 1.4.2。
// user_spec.js
describe("User", function() {
var userController;
beforeEach(function () {
loadFixtures('menu.html');
userController = new MyApp.User.Controller();
});
describe("LoginView", function() {
beforeEach(function() {
// Mock the $.ajax function to prevent XHR:
spyOn($, "ajax").andCallFake(function(params) {});
});
it("should pass email and password with the 'signInForm:submit' event.", function() {
var email = "firstname.name@email.com";
var password = "Passw0rd";
var callback = jasmine.createSpy("FormSubmitSpy");
userController.loginView.$el.find("#signInEmail").val(email);
userController.loginView.$el.find("#signInPassword").val(password);
userController.loginView.bind("signInForm:submit", callback, this);
userController.loginView.ui.signInForm.trigger("submit");
expect(callback).toHaveBeenCalledWith({
email: email,
password: password
});
});
it("should pass name, email and password with the 'signUpForm:submit' event.", function() {
var name = "John Doe";
var email = "firstname.name@email.com";
var password = "Passw0rd";
var callback = jasmine.createSpy("FormSubmitSpy");
userController.loginView.$el.find("#signUpName").val(name);
userController.loginView.$el.find("#signUpMail").val(email);
userController.loginView.$el.find("#signUpPassword").val(password);
userController.loginView.$el.find("#signUpPasswordConfirmation").val(password);
userController.loginView.bind("signUpForm:submit", callback, this);
userController.loginView.ui.signUpForm.trigger("submit");
expect(callback).toHaveBeenCalledWith({
name: name,
email: email,
password: password,
password_confirmation: password
});
});
});
});
The test for the sign-in form runs successful however the test for the sign-up form fails. 登录表单的测试成功运行,但注册表单的测试失败。
Error: Expected spy FormSubmitSpy to have been called with \
[ { name : 'John Doe', email : 'firstname.name@email.com', \
password : 'Passw0rd', password_confirmation : 'Passw0rd' } ] \
but it was never called.
at new jasmine.ExpectationResult (http://localhost:3000/assets/jasmine.js?body=1:114:32)
at null.toHaveBeenCalledWith (http://localhost:3000/assets/jasmine.js?body=1:1235:29)
at null.<anonymous> (http://localhost:3000/assets/user_spec.js?body=1:233:24)
at jasmine.Block.execute (http://localhost:3000/assets/jasmine.js?body=1:1064:17)
at jasmine.Queue.next_ (http://localhost:3000/assets/jasmine.js?body=1:2096:31)
at jasmine.Queue.start (http://localhost:3000/assets/jasmine.js?body=1:2049:8)
at jasmine.Spec.execute (http://localhost:3000/assets/jasmine.js?body=1:2376:14)
at jasmine.Queue.next_ (http://localhost:3000/assets/jasmine.js?body=1:2096:31)
at jasmine.Queue.start (http://localhost:3000/assets/jasmine.js?body=1:2049:8)
at jasmine.Suite.execute (http://localhost:3000/assets/jasmine.js?body=1:2521:14)
Using the forms in the application there is no problem. 使用应用程序中的表单没有问题。 Data is transmitted.
传输数据。 Everything works fine.
一切正常。 Just the test does not.
只是测试没有。
The test however is successful when I delay its execution. 然而,当我延迟执行时,测试成功 。
_.defer(function() {
expect(callback).toHaveBeenCalledWith({
name: name,
email: email,
password: password,
password_confirmation: password
});
});
Why does this work and the "normal" implementation fails? 为什么这样做和“正常”实现失败?
Here is a simplification of the given case: 以下是给定案例的简化:
it("should evaluate true", function() {
var foo = false;
_.defer(function() {
foo = true;
});
expect(foo).toBeTruthy();
});
The Jasmine way to do the same thing without using an underscore function for deferral would be the following: 使用延迟功能而不使用下划线功能执行相同操作的Jasmine方法如下:
var flag = false;
...
runs(function() {
userController.loginView.ui.signInForm.trigger("submit");
setTimeout(function() { flag = true; }, 1);
}
waitsFor(function() {
return flag;
}, "Blah this should never happen", 10);
runs(function() {
expect(callback).toHaveBeenCalledWith({
name: name,
email: email,
password: password,
password_confirmation: password
});
}
@Marc is correct that the issue is with using bind and the way Javascript sends events "sometimes/usually/always" into he next event loop (its how its asynchronous nature works), so since you are spying on a callback you want to make sure that your tests are written to account for that asynchronous behavior. @Marc是正确的,问题是使用bind和Javascript将事件“有时/通常/总是”发送到他的下一个事件循环(它的异步性质如何工作)的方式,所以既然你正在监视你想做的回调确保您的测试是为了解决该异步行为而编写的。
As your tests are written you run the risk that the first test won't pass either sporadically (I'm surprised it works as is). 在你的测试编写时,你冒着第一次测试不会偶尔通过的风险(我很惊讶它的工作原理)。 You are testing an asynchronous event callback in a non asynchronous fashion... make sense?
您正在以非异步方式测试异步事件回调...有意义吗?
The reason you are seeing this problem is because the callback is nested in some other method, probably jQuery bind and jasmine's spy wraps directly over your method so when the test is set up your method isn't executed until the next tick. 你看到这个问题的原因是因为回调嵌套在其他一些方法中,可能是jQuery bind和jasmine的spy直接包装在你的方法上所以当你设置测试时,你的方法直到下一个tick才会被执行。
I found this page: http://trevmex.com/post/7017702464/nesting-spies-to-see-if-a-callback-in-a-deep-nest-has useful as it describes your problem and a potential work around. 我找到了这个页面: http : //trevmex.com/post/7017702464/nesting-spies-to-see-if-a-callback-in-a-deep-nest-有用,因为它描述了你的问题和潜在的工作周围。
However I've discovered it's best not to necessarily test callbacks as they can be considered private methods. 但是我发现最好不要测试回调,因为它们可以被认为是私有方法。 Perhaps you can test its end result?
也许你可以测试它的最终结果?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.