#ruby-on-rails #ruby-on-rails-3.1 #rspec2
#ruby-on-rails #ruby-on-rails-3.1 #rspec2
Вопрос:
Вот неудачный код спецификации для создания в контроллере клиента:
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
У клиента есть как идентификатор продажи, так и идентификатор категории, которые принадлежат таблице user и category соответственно.
Вот ошибка сбоя спецификации:
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)>'
Вот код приложения для создания в контроллере клиента:
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
Вот код в 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
Похоже, что ошибка была вызвана тем, что @customer.save вернул false, а код для «if @customer.save» не был выполнен. Таким образом, проблема может быть в @customer, сгенерированном Factory, что мне кажется хорошим. Код выполняется без каких-либо проблем при сохранении клиента.
Есть предложения? Спасибо.
Ответ №1:
Я бы разбил это на два конкретных теста. Прямо сейчас вы не уверены в двух вещах:
- клиенту говорят сохранить себя?
- Существует ли проверка, которая препятствует сохранению клиента?
Самый быстрый путь — изменить @customer.save на @customer.save! и посмотрите, есть ли какие-либо исключения (это произойдет, если проверка не удалась).
Я рекомендую вам разделить это. Чтобы протестировать # 1, в спецификации контроллера:
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
Затем в вашем customer_spec протестируйте:
it "should be valid with factory specs" do
customer = Customer.new(Factory.attributes_for(:customer))
customer.should be_valid
end
Комментарии:
1. Я добавил ваш код в спецификацию для контроллера. Вот сообщение об ошибке: 1) CustomersController успешно «создает» страницу клиента, должен сообщить клиенту сохранить себя при сбое / ошибке сеанса [: sales]: Customer.stub(:new => cutomer_mock) Ошибка имени: неопределенная локальная переменная или
cutomer_mock' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1::Nested_1:0x43d4d98> # ./spec/controllers/customers_controller_spec.rb:41:in
блок методов (4 уровня) в <top (обязательно)>’2. 2) CustomersController успешно СОЗДАЕТ страницу клиента, которая должна быть действительной при сбое / ошибке заводских спецификаций: customer.should be_valid ожидаемый действительный? чтобы вернуть true, получил false # ./spec/controllers/customers_controller_spec.rb:47:в `блоке (4 уровня) в <top (обязательно)>’
3. В первом примере вы, вероятно, неправильно ввели код. Во-вторых, это доказывает, что проверка мешает вам. Следующие шаги зависят от вас.
4. Видите ли вы какие-либо проблемы с образцами данных, созданными Factory? Я считаю, что есть проблема, но не вижу ее.
5. На самом деле у меня нет возможности судить об этом. Это зависит от ваших заводских определений и от проверки, которую вы определяете для своей модели.
Ответ №2:
post :create, :customer => @customer
решает проблему с выше.