2013-11-01 178 views
1

我有一些控制器測試的問題。以下兩個失敗,但我真的不知道爲什麼。更新和銷燬正在工作。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 

我剛剛添加了從餐廳到地址的關係,更新了我的女工夾具。

這些都是我的燈具:

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

所以,我發現這一點: How is attr_accessible used in Rails 4?

和更新我的方法。但仍然不能工作:(

def restaurant_params 
    params.require(:restaurant).permit(:name, :description, :thumbnail, :banner, addresses_attributes: [ :street, :zip, :city ]) 
end 
+0

你能後的@ restaurant.errors.messages保存失敗後?這幾乎肯定會告訴你什麼是錯的。 –

+0

作爲一個猜測,我懷疑這個問題是一個驗證地址,或類似的東西。如果FactoryGirl屬性不包含地址屬性,或者模型不支持嵌套設置屬性,則可能導致創建失敗並解釋更新工作的原因。 –

+0

嗨,謝謝。但我在哪裏可以找到@ restaurant.errors.messages? – damir

回答

1

首先,感謝大家的幫助。隨着你的想法,我得到了一個解決方案,我現在不使用factoryGirl。正如@PeterGoldstein所說,我使用params。我犯了錯誤,我使用地址而不是addresses_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) 
2

只是把一個puts @ 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 
+0

感謝..將此添加到我的控制器.. 您的測試工作。但是來自puts的消息是:地址不能爲空,但爲什麼它是空白的?我將它添加到factory_girl中? – damir

+0

現在我更糊塗了比以前.. – damir

+0

我猜你需要用戶創建,當你添加addressess到餐廳上後不建(:編譯)回調,你需要創建一個餐廳之前已經創建的地址。或者在測試之前創建的地址並通過IDS那裏將是對參數(像PARAMS = FactoryGirl.attributes_for(:random_restaurant); PARAMS [:addressess] = [@ address.id]),然後執行後。 – arieljuod

1

所以這個問題是在使用

FactoryGirl.attributes_for(:random_restaurant) 

這不會添加地址屬性,而且您的餐廳至少會驗證是否存在屬性。看看你的問題中的POST的屬性:

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"}} 

這裏沒有地址信息。當您創建新餐廳時,您至少需要一個地址。 POST的參數應該如下所示:

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" => "..."}, ...] }} 

我建議您爲創建案例手動構建屬性。如果不出意外,它應該幫助您瞭解如何控制器解析參數

的未經許可的參數問題是一個單獨的問題,並且你已經有了到位的地址參數後可以得到解決。

清楚了嗎?

+0

嗨,是的,這是有道理的。但是,我認爲我現在絕對失去了:)我該怎麼做?我如何建立這些參數? – damir

+0

只需在我的回答中構建一個像這樣的散列。我其實從來沒有使用FactoryGirl.attributes_for - 我的控制器規格有我發佈的參數。大多數控制器規格以這種方式工作。你應該閱讀控制器如何解析參數 - 那麼這將會更有意義。 –

+0

你的意思是這樣的:post:create,{restaurant:{name:'Bar',description:'description',地址:{street:'street',zip:'8888',city:'city'}} } – damir