RSpec 和 Rails 3 - 简单测试失败

发布于 2024-11-04 01:41:35 字数 2451 浏览 0 评论 0原文

RSpec 2.5,Rails 3.0.6 - git://github.com/stevecastaneda/project.git

我正在做一些简单的测试,以确保用户在注册时有效。失败的测试是“应该需要用户名”。产生的错误是:

Failure/Error: new_user(:username => '').should have(1).error_on(:username)
       expected 1 error on :username, got 0

user_spec.rb

require File.dirname(__FILE__) + '/../spec_helper'

describe User do
  def new_user(attributes = {})
    attributes[:username] ||= 'foo'
    attributes[:email] ||= '[email protected]'
    attributes[:password] ||= 'abc123'
    attributes[:password_confirmation] ||= attributes[:password]
    User.new(attributes)
  end

  before(:each) do
    User.delete_all
  end

  it "should be valid" do
    new_user.should be_valid
  end

  it "should require username" do
    new_user(:username => '').should have(1).error_on(:username)
  end
end

User.rb

class User < ActiveRecord::Base
  # new columns need to be added here to be writable through mass assignment
  attr_accessible :username, :email, :password, :password_confirmation

  attr_accessor :password
  before_save :prepare_password

  validates_presence_of :username
  validates_uniqueness_of :username, :email, :allow_blank => true
  validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"
  validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
  validates_presence_of :password, :on => :create
  validates_confirmation_of :password
  validates_length_of :password, :minimum => 4, :allow_blank => true

  # login can be either username or email address
  def self.authenticate(login, pass)
    user = find_by_username(login) || find_by_email(login)
    return user if user && user.password_hash == user.encrypt_password(pass)
  end

  def encrypt_password(pass)
    BCrypt::Engine.hash_secret(pass, password_salt)
  end

  private

  def prepare_password
    unless password.blank?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = encrypt_password(password)
    end
  end
end

正如你所看到的,我只是创建一个新用户(还没有使用工厂,只是简单的测试)空用户名,并且由于 validates_presence_of :username 它应该有错误。

我缺少什么?

RSpec 2.5, Rails 3.0.6 - git://github.com/stevecastaneda/project.git

I'm doing a few simple tests to make sure users are valid when registering. The test that is failing is "should require username". The resulting error is:

Failure/Error: new_user(:username => '').should have(1).error_on(:username)
       expected 1 error on :username, got 0

user_spec.rb

require File.dirname(__FILE__) + '/../spec_helper'

describe User do
  def new_user(attributes = {})
    attributes[:username] ||= 'foo'
    attributes[:email] ||= '[email protected]'
    attributes[:password] ||= 'abc123'
    attributes[:password_confirmation] ||= attributes[:password]
    User.new(attributes)
  end

  before(:each) do
    User.delete_all
  end

  it "should be valid" do
    new_user.should be_valid
  end

  it "should require username" do
    new_user(:username => '').should have(1).error_on(:username)
  end
end

User.rb

class User < ActiveRecord::Base
  # new columns need to be added here to be writable through mass assignment
  attr_accessible :username, :email, :password, :password_confirmation

  attr_accessor :password
  before_save :prepare_password

  validates_presence_of :username
  validates_uniqueness_of :username, :email, :allow_blank => true
  validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"
  validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
  validates_presence_of :password, :on => :create
  validates_confirmation_of :password
  validates_length_of :password, :minimum => 4, :allow_blank => true

  # login can be either username or email address
  def self.authenticate(login, pass)
    user = find_by_username(login) || find_by_email(login)
    return user if user && user.password_hash == user.encrypt_password(pass)
  end

  def encrypt_password(pass)
    BCrypt::Engine.hash_secret(pass, password_salt)
  end

  private

  def prepare_password
    unless password.blank?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = encrypt_password(password)
    end
  end
end

As you can see I'm simply creating a new user (not using factories just yet, just simple tests) with an empty username and because of validates_presence_of :username it should have errors.

What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫﹏色ふ单纯 2024-11-11 01:41:35

由于您使用 Mocha 作为您的模拟框架,因此您需要告诉 Rspec(仅将 Mocha 放入您的 Gemfile 中是不够的)。在您的 spec_helper.rb 文件中,将其更改

config.mock_with :rspec

为:

config.mock_with :mocha

,然后所有测试都会通过。


更多信息:

如果您单独运行它,您的User模型规范实际上工作得很好:

rspec spec/models/user_spec.rb

您的UsersController规范实际上是干扰者,这就是为什么为整个项目运行 rspec 失败的原因。

您的控制器规格先于模型规格运行。在您的控制器规范中,您有几个 User.any_instance.stub... 调用。您的最后一个 UsersController 规范存根 valid? 为 true。这些不仅仅适用于您的控制器规格。一旦您达到了 User 模型规范,对 valid? 的调用仍然会因为此存根而返回 true,因为 Rspec 不知道您正在使用 Mocha。

Since you're using Mocha for your mock framework, you need to tell Rspec this (just putting Mocha in your Gemfile won't be enough). In your spec_helper.rb file, change this:

config.mock_with :rspec

To this:

config.mock_with :mocha

and all of your tests will pass.


More Info:

Your User model spec is actually working perfectly fine, if you run it by itself:

rspec spec/models/user_spec.rb

Your UsersController spec is actually the one interfering, which is why running rspec for your entire project fails.

Your controller specs run before your model specs. In your controller specs, you have a couple User.any_instance.stub... calls. Your very last UsersController spec stubs valid? to be true. These are not scoped only for your controller specs. Once you hit your User model spec, calls to valid? still return true because of this stubbing, since Rspec doesn't know you're using Mocha.

彻夜缠绵 2024-11-11 01:41:35

您需要添加

user = new_user(:username => '')
user.should_not be_valid

否则,不会执行验证,因此不会出现错误。

对我有用:


require 'active_model'

def new_user(attributes = {})
  attributes[:username] ||= 'foo'
  attributes[:email] ||= '[email protected]'
  attributes[:password] ||= 'abc123'
  attributes[:password_confirmation] ||= attributes[:password]
  User.new(attributes)
end

class User
  include ActiveModel::Validations

  attr_accessor :username, :email

  validates_presence_of :username
end

describe User do
  it "should validate" do
    new_user(:username => '').should_not be_valid
  end
end

将其更改

validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"

为:

validates_format_of :username, :with => /^[-\w\._@]+$/i, :message => "should only contain letters, numbers, or .-_@", :unless => lambda {|u| u.username.blank?}

You need to add

user = new_user(:username => '')
user.should_not be_valid

Otherwise the validation is not performed, and, therefor, there're no errors.

Works for me:


require 'active_model'

def new_user(attributes = {})
  attributes[:username] ||= 'foo'
  attributes[:email] ||= '[email protected]'
  attributes[:password] ||= 'abc123'
  attributes[:password_confirmation] ||= attributes[:password]
  User.new(attributes)
end

class User
  include ActiveModel::Validations

  attr_accessor :username, :email

  validates_presence_of :username
end

describe User do
  it "should validate" do
    new_user(:username => '').should_not be_valid
  end
end

Change this:

validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or .-_@"

to this:

validates_format_of :username, :with => /^[-\w\._@]+$/i, :message => "should only contain letters, numbers, or .-_@", :unless => lambda {|u| u.username.blank?}
感受沵的脚步 2024-11-11 01:41:35

实际上,罪魁祸首是您的 users_controller_spec,该行是:

User.any_instance.stubs(:valid?).returns(true)

The culprit, actually, is your users_controller_spec, and the line is:

User.any_instance.stubs(:valid?).returns(true)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文