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
它应该有错误。
我错过了什么?
答案 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)