我使用postgresql 9.1运行rails 3.1.3并使用Rspec进行测试。这是一个基于railstutorial的测试应用程序,是我学习rails的一部分。
我的问题在于spec / models / employee_spec.rb测试。到目前为止,有34个示例,除了三个之外全部通过,并且由于非空约束而失败。以下是失败的测试:
it "should create a new instance given valid attributes" do
Employee.create!(@attr)
end (------ the Employee.create!(@attr) seems to be the problem)
it "should reject duplicate email addresses" do
# Put an employee with a given email address into the database.
Employee.create!(@attr)
employee_with_duplicate_email = Employee.new(@attr)
employee_with_duplicate_email.should_not be_valid
end
it "should reject email addresses identical up to case" do
upcased_email = @attr[:email].upcase
Employee.create!(@attr.merge(:email => upcased_email))
employee_with_upcase_email = Employee.new(@attr)
employee_with_upcase_email.should_not be_valid
end
希望其中一位读过这篇文章的人,如果不是太长,可以给我一些关于如何解决这个问题的指示。(我可以进入postgresql并更改属性,使其接受空值,但是我想认为rspec应该能够处理非null约束)
好的,非常感谢你们所提供的任何帮助,指导和指导。
汤姆。
表的架构:
# == Schema Information
#
# Table name: employees
#
# id :integer not null, primary key
# first_name :string(255) not null
# last_name :string(255) not null
# mi :text
# marital_status :string(255) not null
# gender :string(255) not null
# birth_date :date default(Sat, 20 Aug 1949), not null
# hire_date :date not null
# term_date :date
# primary_position :string(255) not null
# trained_position :string(255)
# email :string(255) not null
# active :boolean default(TRUE), not null
# address1 :string(255) not null
# address2 :string(255)
# city :string(255) not null
# zip_code :string(255) not null
# state :string(255) not null
# emp_home_ph :string(255)
# emp_mobile_ph :string(255)
# emer_contact_first_name :string(255)
# emer_contact_last_name :string(255)
# emer_contact_relationship :string(255)
# emer_contact_ph :string(255)
# created_at :datetime
# updated_at :datetime
#
规范文件(~/spec/models/employee_spec.rb
):
require 'spec_helper'
describe Employee do
before(:each) do
@attr = { :first_name => "Teress", :last_name => "Pottle", :mi => "null",
:marital_status => "Single", :gender => "Female", :birth_date => '1987-04-20',
:hire_date => '2002-01-01', :term_date => "null", :active => "true",
:primary_position => "Job Coach", :trained_position => "null", :email =>
"tpottle@example.com", :address1 => "1 First Ave", :address2 => "null", :city =>
"Frave", :zip_code => "54806", :state => "WI", :emp_home_ph => "null",
:emp_mobile_ph => "null", :emer_contact_first_name => "null",
:emer_contact_last_name => "null", :emer_contact_relationship => "null",
:emer_contact_ph => "null" }
end
it "should create a new instance given valid attributes" do
Employee.create!(@attr)
end
it "should require a first_name" do
no_first_name = Employee.new(@attr.merge(:first_name => ""))
no_first_name.should_not be_valid
end
it "should reject first_name that is too long" do
long_name = "a" * 26
long_first_name = Employee.new(@attr.merge(:first_name => long_name))
long_first_name.should_not be_valid
end
it "should require a last_name" do
no_last_name = Employee.new(@attr.merge(:last_name => ""))
no_last_name.should_not be_valid
end
it "should reject a last_name that is too long" do
long_name = "a" * 26
long_last_name = Employee.new(@attr.merge(:last_name => long_name))
long_last_name.should_not be_valid
end
it "should require a marital_status" do
no_marital_status = Employee.new(@attr.merge(:marital_status => ""))
no_marital_status.should_not be_valid
end
it "should require a gender" do
no_gender = Employee.new(@attr.merge(:gender => ""))
no_gender.should_not be_valid
end
it "should require a birth_date" do
no_birth_date = Employee.new(@attr.merge(:birth_date => ""))
no_birth_date.should_not be_valid
end
it "should require a hire_date" do
no_hire_date = Employee.new(@attr.merge(:hire_date => ""))
no_hire_date.should_not be_valid
end
it "should require a primary_position" do
no_primary_position = Employee.new(@attr.merge(:primary_position => ""))
no_primary_position.should_not be_valid
end
it "should require a email" do
no_email = Employee.new(@attr.merge(:email => ""))
no_email.should_not be_valid
end
it "should require an 'active' setting" do
no_active_setting = Employee.new(@attr.merge(:active => ""))
no_active_setting.should_not be_valid
end
it "should require an address1" do
no_address1 = Employee.new(@attr.merge(:address1 => ""))
no_address1.should_not be_valid
end
it "should require a city" do
no_city = Employee.new(@attr.merge(:city => ""))
no_city.should_not be_valid
end
it "should require a zip_code" do
no_zip_code = Employee.new(@attr.merge(:zip_code => ""))
no_zip_code.should_not be_valid
end
it "should require a state" do
no_state = Employee.new(@attr.merge(:state => ""))
no_state.should_not be_valid
end
it "should accept valid email addresses" do
addresses = %w[user@foo.com THE_USER@foo.bar.org first.last@foo.jp]
addresses.each do |address|
valid_email_employee = Employee.new(@attr.merge(:email => address))
valid_email_employee.should be_valid
end
end
it "should reject invalid email addresses" do
addresses = %w[user@foo,com user_at_foo.org example.user@foo.]
addresses.each do |address|
invalid_email_employee = Employee.new(@attr.merge(:email => address))
invalid_email_employee.should_not be_valid
end
end
it "should reject duplicate email addresses" do
# Put an employee with a given email address into the database.
Employee.create!(@attr)
employee_with_duplicate_email = Employee.new(@attr)
employee_with_duplicate_email.should_not be_valid
end
it "should reject email addresses identical up to case" do
upcased_email = @attr[:email].upcase
Employee.create!(@attr.merge(:email => upcased_email))
employee_with_upcase_email = Employee.new(@attr)
employee_with_upcase_email.should_not be_valid
end
end
Employee类(~/app/models/employee.rb
):
class Employee < ActiveRecord::Base
attr_accessor :first_name, :last_name, :mi, :marital_status, :gender, :birth_date,
:hire_date, :term_date, :primary_position, :trained_position, :email, :active,
:address1, :address2, :city, :zip_code, :state, :emp_home_ph, :emp_mobile_ph,
:emer_contact_first_name, :emer_contact_last_name, :emer_contact_relationship,
:emer_contact_ph
email_regex = /([\w+.]+)@[a-z0-9\-.]+\.[a-z]+/i
date_regex = /^[0-9]{4}[-][0-9]{2}[-][0-9]{2}$/
validates(:marital_status, :gender, :primary_position, :active, :address1, :city,
:zip_code, :state, :presence => true)
validates(:first_name, :last_name, :presence => true,
:length => { :maximum => 25 })
validates(:birth_date, :hire_date, :presence => true,
:format => { :with => date_regex })
validates(:email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false})
end
运行rspec时会发生什么:
loading autotest/rails_rspec2
/home/tom/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -rrubygems -S /home/tom/.rvm/gems
/ruby-1.9.3-p0@latest/gems/rspec-core-2.7.1/exe/rspec --tty
'/home/tom/rails_projects/tracking /spec/controllers/employees_controller_spec.rb'
'/home/tom/rails_projects/tracking/spec/controllers/pages_controller_spec.rb' '/home
/tom/rails_projects/tracking/spec/models/employee_spec.rb' '/home/tom/rails_projects
/tracking/spec/requests/layout_links_spec.rb'
........F.................FF......
Failures:
1) Employee should create a new instance given valid attributes
Failure/Error: Employee.create!(@attr)
ActiveRecord::StatementInvalid:
PGError: ERROR: null value in column "first_name" violates not-null constraint
: INSERT INTO "employees" ("active", "address1", "address2", "birth_date",
"city", "created_at", "email", "emer_contact_first_name",
"emer_contact_last_name", "emer_contact_ph", "emer_contact_relationship",
"emp_home_ph", "emp_mobile_ph", "first_name", "gender", "hire_date", "last_name",
"marital_status", "mi", "primary_position", "state", "term_date",
"trained_position", "updated_at", "zip_code")
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16,
$17, $18, $19, $20, $21, $22, $23, $24, $25) RETURNING "id"
# ./spec/models/employee_spec.rb:42:in `block (2 levels) in <top (required)>'
2) Employee should reject duplicate email addresses
Failure/Error: Employee.create!(@attr)
ActiveRecord::StatementInvalid:
PGError: ERROR: null value in column "first_name" violates not-null constraint
: INSERT INTO "employees" ("active", "address1", "address2", "birth_date", "city",
"created_at", "email", "emer_contact_first_name", "emer_contact_last_name",
"emer_contact_ph", "emer_contact_relationship", "emp_home_ph", "emp_mobile_ph",
"first_name", "gender", "hire_date", "last_name", "marital_status", "mi",
"primary_position", "state", "term_date", "trained_position", "updated_at",
"zip_code")
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16,
$17, $18, $19, $20, $21, $22, $23, $24, $25) RETURNING "id"
# ./spec/models/employee_spec.rb:140:in `block (2 levels) in <top (required)>'
3) Employee should reject email addresses identical up to case
Failure/Error: Employee.create!(@attr.merge(:email => upcased_email))
ActiveRecord::StatementInvalid:
PGError: ERROR: null value in column "first_name" violates not-null constraint
: INSERT INTO "employees" ("active", "address1", "address2", "birth_date", "city",
"created_at", "email", "emer_contact_first_name", "emer_contact_last_name",
"emer_contact_ph", "emer_contact_relationship", "emp_home_ph", "emp_mobile_ph",
"first_name", "gender", "hire_date", "last_name", "marital_status", "mi",
"primary_position", "state", "term_date", "trained_position", "updated_at",
"zip_code") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14,
$15, $16,$17, $18, $19, $20, $21, $22, $23, $24, $25) RETURNING "id"
# ./spec/models/employee_spec.rb:147:in `block (2 levels) in <top (required)>'
Finished in 19.24 seconds
34 examples, 3 failures
Failed examples:
rspec ./spec/models/employee_spec.rb:41 # Employee should create a new instance given
valid attributes
rspec ./spec/models/employee_spec.rb:138 # Employee should reject duplicate email
addresses
rspec ./spec/models/employee_spec.rb:145 # Employee should reject email addresses
identical up to case
答案 0 :(得分:2)
您的问题不在于您的测试,您的问题在于您的Employee
课程。你的课程从这开始:
class Employee < ActiveRecord::Base
attr_accessor :first_name, :last_name, :mi, :marital_status, :gender, :birth_date,
:hire_date, :term_date, :primary_position, :trained_position, :email, :active,
:address1, :address2, :city, :zip_code, :state, :emp_home_ph, :emp_mobile_ph,
:emer_contact_first_name, :emer_contact_last_name, :emer_contact_relationship,
:emer_contact_ph
但您不需要或想要在此使用attr_accessor
。普通对象属性(attr_accessor
创建的)与ActiveRecord属性不同。 ActiveRecord将检查表的结构,并为数据库支持的属性创建自己的内部存储,并为这些属性创建一套访问器和mutator方法;在内部,ActiveRecord将使用这些访问器方法来查看对象中的内容。然后,使用attr_accessor
将列声明为对象属性,attr_accessor
创建自己的访问器和mutator方法,以替换ActiveRecord。结果是object.first_name
将在@first_name
中查找object
实例变量,但不会有这样的事情,Employee.create
会在ActiveRecord中设置first_name
属性,不 @first_name
实例值。
解决方案是摆脱班级中的attr_accessor
语句。然后与教程并行阅读Rails Guides。