2016-04-10 54 views
1

我鼓勵自己以下鏈接,http://railscasts.com/episodes/163-self-referential-association,但rspec測試並不容易。RSpec測試與followerships /友誼有很多通過用戶

用戶模型:

class User < ActiveRecord::Base 

    # Associations 
    has_many :followerships 
    has_many :followers, :through => :followerships 
    has_many :inverse_followerships, :class_name => "Followership", :foreign_key => "follower_id" 
    has_many :inverse_followers, :through => :inverse_followerships, :source => :user 
end 

追隨者型號:

class Followership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :follower, :class_name => "User" 
end 

followerhip廠:

FactoryGirl.define do 
    factory :followership do 
    user_id 1 
    follower_id 1 
    end 
end 

followerships控制器:

class FollowershipsController < InheritedResources::Base 
    def create 
    @followership = current_user.followerships.build(:follower_id => params[:follower_id]) 
    if @followership.save 
     flash[:notice] = "Following." 
     redirect_to root_url 
    else 
     flash[:error] = "Unable to follow." 
     redirect_to root_url 
    end 
    end 

    def destroy 
    @followership = current_user.followerships.find(params[:id]) 
    @followership.destroy 
    flash[:notice] = "Removed followership." 
    redirect_to current_user 
    end 
end 

folowerships控制器規範(這是完全錯誤的):

require 'rails_helper' 

describe FollowershipsController do 
    let!(:followership) { create(:followership) } 
    let!(:follower) { followership.follower } 
    let!(:user) { create(:user) } 

    before do 
    sign_in :user, user 
    end 

    describe "#create" do 
    it "saves the followership" do 
     post :create, followership: { follower_id: follower } 

     expect(response).to redirect_to(root_path) 
     expect(assigns(:followership).followership.followers).to eq(user) 
     expect(flash[:notice]).to eq("Following.") 
    end 

    it "fails to save followership" do 
     expect(post :create, followership: { follower_id: follower }).to redirect_to(root_path) 
     expect(flash[:notice]).to eq("Unable to follow.") 
    end 
    end 

    describe "#destroy" do 
    it "deletes the followership" do 
     expect { 
     delete :destroy, id: follower 
     }.to change(Followership, :count).by(-1) 

     expect(flash[:notice]).to eq("Removed followership.") 
    end 
    end 

end 

錯誤從followerships控制器Rspec的

FollowershipsController 
    #destroy 
    deletes the followership (FAILED - 1) 
    #create 
    saves the followership (FAILED - 2) 
    fails to save followership (FAILED - 3) 

Failures: 

    1) FollowershipsController#destroy deletes the followership 
    Failure/Error: delete :destroy, id: follower 

    ActionController::UrlGenerationError: 
     No route matches {:action=>"destroy", :controller=>"followerships", :id=>nil} 

    2) FollowershipsController#create saves the followership 
    Failure/Error: expect(assigns(:followership).followership.followers).to eq(user) 

    NoMethodError: 
     undefined method `followership' for #<Followership:0x00000109f69780> 

    3) FollowershipsController#create fails to save followership 
    Failure/Error: expect(flash[:notice]).to eq("Unable to follow.") 

     expected: "Unable to follow." 
      got: "Following." 

     (compared using ==) 

感謝您的幫助: )

回答

2

let命令使用延遲評估,所以這些記錄直到調用纔會實際創建。使用let!語法,以確保他們之前創建你的測試運行:

let!(:followership) { create(:followership) } 
    let!(:follower) { followership.follower } 
    let!(:user) { create(:user) } 

確保您的驗證也只允許以下的創造,如果它不存在爲對用戶:

class Followership < ActiveRecord::Base 
    validates_uniqueness_of :user_id, scope: :follower_id 

而且,它不保證該follower/followership關係將屬於user因爲user不一定有id的1

最後,assigns是一種方法,所以語法應該是assigns(:followership)不是assigns[:followership]

+0

嗨安東尼,我接受了你的意見。我知道工廠和Rspec不工作...有什麼想法?謝謝 – Jony