简体   繁体   English

使用.toHaveBeenCalledWith的Jasmine测试失败,用于注册表单

[英]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. 只是测试没有。

Workaround 解决方法

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.

相关问题 当用户使用测试脚本在邮递员中登录/注册时,无法将 JWT 令牌设置为环境变量? - Unable to set JWT token as environment variable when user login/sign-up in postman using test script? 为使用 AWS(特别是 S3 存储桶)托管的网站页面创建注册表单(类似于 mailchimp) - Creating a sign-up form (similar to mailchimp) for a website page that is hosted using AWS (S3 bucket specifically) 根据下拉菜单更改注册表格? - Change sign-up form depending on the drop down-menu? React 登录/注册表单切换问题 - React login/sign-up form toggle issues 使用Jasmine的toHaveBeenCalledWith方法的对象类型 - Using object types with Jasmine's toHaveBeenCalledWith method 当注册是仅电子邮件登录时如何自动测试用户注册 - How to automated test a user sign-Up when the signUp is a email-only-sign-In 防止用户在 Firebase 中注册? - Preventing user sign-up in Firebase? 填写注册表后,Bootstrap 模态在同一模态上显示“注册成功”文本 - Bootstrap modal to show "Registration Success" text on the same modal after filling-in the sign-up form 显示注册表单时如何模糊登录的背景? - How do I blur login's background when the sign-up form is displayed? 有没有办法可以将数据从注册表单发送到另一个 HTML 页面? - Is there a way that I can send data from Sign-Up Form to another HTML Page?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM