问题
Here is the failed spec code for create in customer controller:
describe CustomersController do
before(:each) do
#the following recognizes that there is a before filter without execution of it.
controller.should_receive(:require_signin)
controller.should_receive(:require_employee)
end
render_views
describe "'create' successful" do
before(:each) do
category = Factory(:category)
sales = Factory(:user)
@customer = Factory.attributes_for(:customer, :category1_id => category.id, :sales_id => sales.id)
session[:sales] = true
session[:user_id] = sales.id
session[:user_name] = sales.name
session[:page_step] = 1
session['page1'] = customers_path
end
it "should create one customer record" do
lambda do
post 'create', @customer
end.should change(Customer, :count).by(1)
end
it "should redirect to customers path" do
put 'create', @customer
flash[:notice].should_not be_nil
response.should redirect_to(customers_path)
end
end
end
The customer has both sales id and category id which belong to user and category table respectively.
Here is the spec failure error:
1) CustomersController GET customer page 'create' successful should create one customer record
Failure/Error: lambda do
count should have been changed by 1, but was changed by 0
# ./spec/controllers/customers_controller_spec.rb:37:in `block (4 levels) in <top (required)>'
2) CustomersController GET customer page 'create' successful should redirect to customers path
Failure/Error: flash[:notice].should_not be_nil
expected: not nil
got: nil
# ./spec/controllers/customers_controller_spec.rb:44:in `block (4 levels) in <top (required)>'
Here is the app code for create in customer controller:
def create
if session[:sales]
@customer = Customer.new(params[:customer], :as => :roles_new_update)
@customer.sales_id = session[:user_id]
if @customer.save
@message = "New customer #{params[:name]} was created. Please check it out"
@subject = "New customer #{params[:name]} was created BY {#session[:user_name]}"
UserMailer.notify_tl_dh_ch_ceo(@message, @subject, session[:user_id])
redirect_to session[('page' + session[:page_step].to_s).to_sym], :notice => 'Customer was created successfaully!'
else
render 'new', :notice => 'Customer was not saved!'
end
end
end
Here is the code in factories.rb:
Factory.define :customer do |c|
c.name "test customer"
c.short_name "test"
c.email "t@acom.com"
c.phone "12345678"
c.cell "1234567890"
c.active 1
c.category1_id 2
c.sales_id 1
c.address "1276 S. Highland Ave, Lombard, IL 67034"
c.contact "Jun C"
end
Factory.define :category do |c|
c.name "category name"
c.description "test category"
c.active true
end
Factory.define :user do |user|
user.name "Test User"
user.email "test@test.com"
user.password "password1"
user.password_confirmation "password1"
user.status "active"
user.user_type "employee"
end
It seems that the error was caused by @customer.save returning false and the code for "if @customer.save" was not executed. So the problem may be with the @customer generated by Factory which seems good to me. The code is executed without any problem when saving a customer.
Any suggestions? Thanks.
回答1:
I would break this up into two specific tests. Right now you're unsure of two things:
- is the customer is being told to save itself?
- Is there a validation that is preventing customer from being saved?
The quickest path is to change @customer.save to @customer.save! and see if there are any exceptions raised (it will do so if a validation failed).
I recommend you split this up though. To test #1, in the controller spec:
it "should tell the customer to save itself when there is a session[:sales]" do
session[:sales] = true
customer_mock = double(:customer)
customer_mock.should_receive(:sales_id=)
customer_mock.should_receive(:save).and_return(:true)
Customer.stub(:new => cutomer_mock)
post 'create'
end
Then in your customer_spec, test out:
it "should be valid with factory specs" do
customer = Customer.new(Factory.attributes_for(:customer))
customer.should be_valid
end
回答2:
post :create, :customer => @customer
solves the problem with above.
来源:https://stackoverflow.com/questions/7867361/object-save-failed-in-spec-data-validation