Тесты Ruby on Rails rspec проваливаются, но не должны
У меня проблема с некоторыми тестами контроллера. следующие два терпят неудачу, но я действительно не знаю почему. Обновление и уничтожение работают.
Я использую Rails 4.0 и mongoid.
describe 'POST create' do
context 'with valid attributes' do
it 'creates a new restaurant' do
expect {
post :create, restaurant: FactoryGirl.attributes_for(:random_restaurant)
}.to change(Restaurant, :count).by(1)
end
it 'redirects to the new restaurant' do
post :create, restaurant: FactoryGirl.attributes_for(:random_restaurant)
response.should redirect_to Restaurant.last
end
end
я только добавил отношение от ресторана к адресу, обновил свои приспособления Factorygirl.
это мои крепления:
factory :random_restaurant, parent: :restaurant do |r|
r.name {Faker::Company.name}
r.description {Faker::Lorem.sentences}
after(:build) do |restaurant|
restaurant.addresses << FactoryGirl.build(:random_address)
end
end
factory :random_address, parent: :address do |a|
a.street {Faker::Address.street_address}
a.zip {Faker::Address.zip_code}
a.city {Faker::Address.city}
end
метод создания поста контроллера выглядит следующим образом (по умолчанию)
# POST /restaurants
# POST /restaurants.json
def create
@restaurant = Restaurant.new(restaurant_params)
respond_to do |format|
if @restaurant.save
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully created.' }
format.json { render action: 'show', status: :created, location: @restaurant }
else
format.html { render action: 'new' }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
ошибки:
Failures: 1) RestaurantsController POST create with valid attributes creates a new restaurant
Failure/Error: expect {
count should have been changed by 1, but was changed by 0
# ./spec/controllers/restaurants_controller_spec.rb:39:in `block (4 levels) in <top (required)>'
2) RestaurantsController POST create with valid attributes redirects to the new restaurant
Failure/Error: response.should redirect_to Restaurant.last
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/restaurants_controller_spec.rb:46:in `block (4 levels) in <top (required)>'
Finished in 0.85251 seconds
19 examples, 2 failures
Failed examples:
rspec ./spec/controllers/restaurants_controller_spec.rb:38 # RestaurantsController POST create with valid attributes creates a new restaurant
rspec ./spec/controllers/restaurants_controller_spec.rb:44 # RestaurantsController POST create with valid attributes redirects to the new restaurant
Вот тест обновления, который работает:
describe 'PUT update' do
before :each do
@restaurant = FactoryGirl.create(:random_restaurant)
end
context 'with valid attributes' do
it 'locates the requested @restaurant' do
put :update, id: @restaurant, restaurant: FactoryGirl.attributes_for(:restaurant)
assigns(:restaurant).should eq(@restaurant)
end
it 'changes @restaurants attributes' do
put :update, id: @restaurant, restaurant: FactoryGirl.attributes_for(:restaurant)
@restaurant.reload
@restaurant.name.should eq('A Lodge')
@restaurant.description.should eq('A Bar')
end
it 'redirects to @restaurant' do
put :update, id: @restaurant, restaurant: FactoryGirl.attributes_for(:restaurant)
response.should redirect_to @restaurant
end
end
Кто-нибудь знает, почему это не удается и как я могу решить это? большое спасибо вам
Обновление: Вы имели в виду что-то подобное? это из test.log
Processing by RestaurantsController#create as HTML
Parameters: {"restaurant"=>{"name"=>"Schneider, Franecki and Tillman",
"description"=>["Quae labore quia officia soluta voluptatibus.", "Et error incidunt beatae laborum a libero officiis.", "Non excepturi dolor vel."],
"thumbnail"=>"some url", "banner"=>"some url"}}
**Unpermitted parameters: thumbnail, banner**
Обновление 2
эти тесты также работают:
describe Restaurant do
it 'has a valid factory' do
FactoryGirl.create(:random_restaurant).should be_valid
end
it 'has an invalid factory' do
FactoryGirl.build(:random_restaurant_with_invalid_address).should_not be_valid
end
it 'is invalid without a name' do
FactoryGirl.build(:random_restaurant, name: nil).should_not be_valid
end
it 'is invalid without a description' do
FactoryGirl.build(:random_restaurant, description: nil).should_not be_valid
end
it 'is invalid without an address' do
FactoryGirl.build(:random_restaurant_with_invalid_address).should_not be_valid
end
it 'creates an address when created' do
FactoryGirl.create(:random_restaurant)
end
end
Обновление 3
Мои модели:
class Restaurant
include Mongoid::Document
has_many :addresses, dependent: :destroy
validates :name, presence: true
validates :description, presence: true
validates :addresses, presence: true
field :name, type: String
field :description, type: String
field :thumbnail, type: String
field :banner, type: String
end
class Address
include Mongoid::Document
belongs_to :restaurant
validates :street, presence: true
validates :zip, presence: true
validates :city, presence: true
field :street, type: String
field :zip, type: Integer
field :city, type: String
def full_address
zip_city = [zip, city].join ' '
[street, zip_city].join ', '
end
end
Обновление 4
Итак, я нашел это: Как attr_accessible используется в Rails 4?
и обновил мой метод. но все равно не работает:(
def restaurant_params
params.require(:restaurant).permit(:name, :description, :thumbnail, :banner, addresses_attributes: [ :street, :zip, :city ])
end
3 ответа
Прежде всего, спасибо всем за помощь. С вашими идеями у меня есть решение, я не использую factoryGirl. Я использую, как упоминал @PeterGoldstein, params. Я сделал ошибку, что использовал адреса вместо address_attributes. Я не знаю, почему я должен использовать это, как я должен был, но я собираюсь выяснить это.
вот мое решение, которое работает для меня:
expect {
post :create, restaurant: { name: 'A-Lodge', description: 'descr',
thumbnail: 'this is url to thumbnail', banner: 'this is url to banner',
addresses_attributes: [ { street: 'street', zip: '8888', city: 'city' } ] }
}.to change(Restaurant, :count).by(1)
Просто поместите на контроллере put @restaurant.errors.full_messages, похоже, он не прошел валидацию
respond_to do |format|
if @restaurant.save
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully created.' }
format.json { render action: 'show', status: :created, location: @restaurant }
else
puts @restaurant.errors.full_messages
format.html { render action: 'new' }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
не идти и запустить эту спецификацию и проверить вывод на терминале
Вы также можете добавить эту спецификацию для проверки своей фабрики, таким образом, вы можете быть уверены, что ваша фабрика работает правильно:
it 'creates a valid restaurant from factory girl' do
rest = FactoryGirl.build :random_restaurant
rest.should be_valid
end
Таким образом, проблема заключается в использовании
FactoryGirl.attributes_for(:random_restaurant)
это не добавляет атрибуты адреса, и ваш ресторан проверяет наличие хотя бы одного атрибута. Посмотрите на атрибуты POSTed из вашего вопроса:
Parameters: {"restaurant"=>{"name"=>"Schneider, Franecki and Tillman",
"description"=>["Quae labore quia officia soluta voluptatibus.",
"Et error incidunt beatae laborum a libero officiis.",
"Non excepturi dolor vel."],
"thumbnail"=>"some url", "banner"=>"some url"}}
Здесь нет информации об адресе. Когда вы создаете новый ресторан, вам нужен как минимум один адрес. Параметры POSTed должны выглядеть следующим образом:
Parameters: {"restaurant"=>{"name"=>"Schneider, Franecki and Tillman",
"description"=>["Quae labore quia officia soluta voluptatibus.",
"Et error incidunt beatae laborum a libero officiis.",
"Non excepturi dolor vel."],
"thumbnail"=>"some url", "banner"=>"some url",
"addresses"=>[{"street" => "...", "city => "...", "zip" => "..."}, ...] }}
Я предлагаю вам создать атрибуты вручную для создания дела. Если ничего другого, это должно помочь вам понять, как контроллер анализирует параметры
Вопрос о недопустимых параметрах - это отдельная проблема, и ее можно решить после того, как вы установили параметры адреса.
Это понятно?