http://everydayrails.com/2012/03/19/testing-series-rspec-models-factory-girl.html# 离开本教程目前。我正在添加另一个我从rails应用程序教程开始的项目。
我去创建我的模型规格 contact_spec.rb
require 'spec_helper'
describe Contact do
it "has a valid factory" do
FactoryGirl.create(:contact).should be_valid
end
it "is invalid without a firstname"
it "is invalid without a lastname"
it "returns a contact's full name as a string"
end
工厂/ contacts.rb
require 'faker'
FactoryGirl.define do
factory :contact do |f|
f.firstname { Faker::Name.first_name }
f.lastname { Faker::Name.last_name }
end
end
我运行rspec并收到此错误:
1) Contact has a valid factory
Failure/Error: FactoryGirl.create(:contact).should be_valid
NoMethodError:
undefined method `firstname=' for #<Contact name: nil, email: nil, content: nil>
# ./spec/models/contact_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.22028 seconds
4 examples, 1 failure, 3 pending
这是我的联系模式
class Contact < ActiveRecord::Base
has_no_table
column :name, :string
column :email, :string
column :content, :string
validates_presence_of :name
validates_presence_of :email
validates_presence_of :content
validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
validates_length_of :content, :maximum => 500
def update_spreadsheet
connection = GoogleDrive.login(ENV["GMAIL_USERNAME"], ENV["GMAIL_PASSWORD"])
ss = connection.spreadsheet_by_title('Learn-Rails-Example')
if ss.nil?
ss = connection.create_spreadsheet('Learn-Rails-Example')
end
ws = ss.worksheets[0]
last_row = 1 + ws.num_rows
ws[last_row, 1] = Time.new
ws[last_row, 2] = self.name
ws[last_row, 3] = self.email
ws[last_row, 4] = self.content
ws.save
end
end
和我的contactS_controller
class ContactsController < ApplicationController
def new
@contact = Contact.new
end
def create
@contact = Contact.new(secure_params[:contact])
if @contact.valid?
@contact.update_spreadsheet
UserMailer.contact_email(@contact).deliver
flash[:notice] = "Message sent from #{@contact.name}."
redirect_to root_path
else
render :new
end
end
private
def secure_params
params.require(:contact).permit(:name, :email, :content)
end
end
我尝试更改:名称为:firstname,和:lastname并最终收到此新错误
1) Contact has a valid factory
Failure/Error: FactoryGirl.create(:contact).should be_valid
ActiveRecord::RecordInvalid:
Validation failed: Email can't be blank, Email is invalid, Content can't be blank
# ./spec/models/contact_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.22596 seconds
4 examples, 1 failure, 3 pending
Failed examples:
rspec ./spec/models/contact_spec.rb:4 # Contact has a valid factory
我的猜测是,当我参考:联系时,我没有正确定义。
修改 添加Faker :: Internet.email attr引发了一个新错误
1) Contact has a valid factory
Failure/Error: FactoryGirl.create(:contact).should be_valid
ActiveRecord::RecordInvalid:
Validation failed: Content can't be blank
# ./spec/models/contact_spec.rb:5:in `block (2 levels) in <top (required)>'
所以我评论出validates_presence_of:content,column:content和validates_length_of:content并得到这个
1) Contact has a valid factory
Failure/Error: FactoryGirl.create(:contact).should be_valid
ActiveRecord::Tableless::NoDatabase:
Can't #create_record a Tableless object
# ./spec/models/contact_spec.rb:5:in `block (2 levels) in <top (required)>'
所以似乎事情正在起作用,因为我应用它们或带走,我显然在我编写的代码与一个教程之间有很多冲突,并使用rspec factory_girl和faker添加此方法
编辑2 所以在添加了电子邮件和内容attr之后,我继续填写剩余的规格“无先生/姓氏无效”:
describe Contact do
it "has a valid factory" do
FactoryGirl.build(:contact).should be_valid
end
it "is invalid without a firstname" do
FactoryGirl.build(:contact, lastname: nil).should_not be_valid
end
it "is invalid without a lastname" do
FactoryGirl.build(:contact, lastname: nil).should_not be_valid
end
it "returns a contact's full name as a string"
end
我的测试没有错误传递:
is invalid without a lastname
has a valid factory
is invalid without a firstname
returns a contact's full name as a string (PENDING: Not yet implemented)
Pending:
Contact returns a contact's full name as a string
# Not yet implemented
# ./spec/models/contact_spec.rb:15
Finished in 0.22146 seconds
4 examples, 0 failures, 1 pending
谢谢你sonnyhe2002让我通过这个!非常感谢!
答案 0 :(得分:1)
您需要向工厂添加电子邮件attr
FactoryGirl.define do
factory :contact do |f|
f.firstname { Faker::Name.first_name }
f.lastname { Faker::Name.last_name }
f.email { Faker::Internet.email }
f.content 'This is content'
end
end
由于您使用的是has_no_table,我认为工厂无法将其保存到数据库中。
您应该使用'build'而不是'create'
FactoryGirl.build(:contact).should be_valid
答案 1 :(得分:0)
您确定数据库中有firstname
列吗?确保db/schema.rb
的{{1}}表格中包含firstname
列,并确保您已运行contacts
答案 2 :(得分:0)
给出的错误非常具有自我描述性:您的email
和content
属性上有一些验证器,但您没有在Contact
工厂中设置这些属性以使您的模型有效。
编辑:请将此添加到您的联系工厂:
f.email 'email@example.com'
f.content 'a content'
答案 3 :(得分:0)
在你的模特中:
validates_presence_of :name
validates_presence_of :email
validates_presence_of :content
validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
validates_length_of :content, :maximum => 500
因此,在创建FactoryGirl
用户时,您需要考虑上述事实。您只处理电子邮件和名称的存在,但还需要处理内容的存在,其长度必须少于500个字符
答案 4 :(得分:0)
FactoryGirl现在由FactoryBot代替。不赞成使用FactoryGirl。
FactoryBot版本5及更高版本在创建工厂时仅支持动态属性。
因此解决方案是:-
FactoryBot.define do
factory :user do
name { "Ron" }
email { "ron@gmail.com" }
password { "ronY123" }
password_confirmation { "ronY123" }
end
end