RSpec和Rails 3 - 简单测试失败

时间:2011-04-27 21:12:46

标签: ruby-on-rails-3 rspec

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] ||= 'foo@example.com'
    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它应该有错误。

我错过了什么?

3 个答案:

答案 0 :(得分:2)

由于你正在使用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?是真的。这些不仅适用于您的控制器规格。一旦达到User模型规范,由于Rspec不知道您正在使用Mocha,因此对此valid?的调用仍会返回true。

答案 1 :(得分:1)

您需要添加

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

否则不执行验证,因此没有错误。

适合我:


require 'active_model'

def new_user(attributes = {})
  attributes[:username] ||= 'foo'
  attributes[:email] ||= 'foo@example.com'
  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?}

答案 2 :(得分:1)

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

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