2011-12-09 108 views
2

我正在使用postgresql 9.1运行rails 3.1.3并使用Rspec进行测试。这是一个基于railstutorial的测试应用程序,作为我学习rails的一部分。Rspec + Postgresql9.1违反非空约束?

我的问题是与spec/models/employee_spec.rb测试。到目前为止,有34个例子,除3个之外的所有通过,并且由于非空约束而失败。以下是失败的测试:

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应该能够处理非空约束)

好吧,谢谢你和所有的帮助,指针和指导,你可以给。

汤姆。

表的模式:

# == 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 => 
    "[email protected]", :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[[email protected] [email protected] [email protected]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[[email protected],com user_at_foo.org [email protected]] 
     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 
/[email protected]/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

你得到的错误信息是什么?哪个“非空”约束被打中? – araqnid

+0

另外显示包含约束定义的表结构。 – Kuberchaun

+0

您的测试属性('@ attr')不完整,错误信息会告诉您哪些属性丢失。 –

回答

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将检查表的结构并为数据库支持的属性创建自己的内部存储,并为这些属性创建一套访问器和增变器方法;在内部,ActiveRecord将使用这些访问器方法来查看对象中的内容。然后,您使用attr_accessor将这些列声明为对象属性,并且attr_accessor创建它自己的替代ActiveRecord的访问器和变种方法。其结果是,object.first_name将寻找在object@first_name实例变量,但不会有这样的事情,Employee.create将设置在ActiveRecord的的属性first_name@first_name实例值。

解决方案是摆脱你的班级中的attr_accessor声明。然后在阅读教程的同时阅读Rails Guides

+0

谢谢@mu太短....这是一个胜利者....我关闭阅读(attr_accessor)。谢谢你的帮助。 – hlogoma

相关问题