2010-03-31 5 views
10

Ich habe zwei Modelle bekam:RSpec, verschachtelte Ressource Methoden stubbing

class Solution < ActiveRecord::Base 
    belongs_to :owner, :class_name => "User", :foreign_key => :user_id 
end 

class User < ActiveRecord::Base 
    has_many :solutions 
end 

und ich Nest Lösungen innerhalb Anwender wie folgt aus:

ActionController::Routing::Routes.draw do |map| 
    map.resources :users, :has_many => :solutions 
end 

und schließlich ist hier die Aktion I "m zu spec versuchen :

class SolutionsController < ApplicationController 
    before_filter :load_user 

    def show 
    if(@user) 
     @solution = @user.solutions.find(params[:id]) 
    else 
     @solution = Solution.find(params[:id]) 
    end 
    end 

    private 

    def load_user 
    @user = User.find(params[:user_id]) unless params[:user_id].nil? 
    end 
end 

Meine Frage ist, wie zum Teufel tun Spec ich @user.solutions.find(params[:id])

Hier ist meine aktuelle Spezifikation:

describe SolutionsController do 

    before(:each) do 
    @user = Factory.create(:user) 
    @solution = Factory.create(:solution) 
    end 

    describe "GET Show," do 

    before(:each) do 
     Solution.stub!(:find).with(@solution.id.to_s).and_return(@solution) 
     User.stub!(:find).with(@user.id.to_s).and_return(@user) 
    end 

    context "when looking at a solution through a user's profile" do 

     it "should find the specified solution" do 
     Solution.should_receive(:find).with(@solution.id.to_s).and_return(@solution) 
     get :show, :user_id => @user.id, :id => @solution.id 
     end 
    end 
    end 

Aber das wird mir die folgende Fehlermeldung:

1)Spec::Mocks::MockExpectationError in 'SolutionsController GET Show, when looking at a solution through a user's profile should find the specified solution' 
<Solution(id: integer, title: string, created_at: datetime, updated_at: datetime, software_file_name: string, software_content_type: string, software_file_size: string, language: string, price: string, software_updated_at: datetime, description: text, user_id: integer) (class)> received :find with unexpected arguments 
    expected: ("6") 
    got: ("6", {:group=>nil, :having=>nil, :limit=>nil, :offset=>nil, :joins=>nil, :include=>nil, :select=>nil, :readonly=>nil, :conditions=>"\"solutions\".user_id = 34"}) 

jemand kann mir helfen mit, wie ich @user.solutions.new(params[:id]) Stummel kann?

Antwort

25

Sieht so aus, als hätte ich meine eigene Antwort gefunden, aber ich werde sie hier veröffentlichen, da ich im Internet nicht viel davon zu finden finde.

RSpec hat eine Methode namens stub_chain: http://apidock.com/rspec/Spec/Mocks/Methods/stub_chain

, die wie es einfach Stummel ein Verfahren macht:

@solution = @user.solutions.find(params[:id]) 

, indem Sie diese:

@user.stub_chain(:solutions, :find).with(@solution.id.to_s).and_return(@solution) 

So dann kann ich ein schreiben RSpec Test wie folgt:

it "should find the specified solution" do 
    @user.solutions.should_receive(:find).with(@solution.id.to_s).and_return(@solution) 
    get :show, :user_id => @user.id, :id => @solution.id 
end 

Und meine Spezifikation besteht. Allerdings lerne ich immer noch hier, also wenn jemand denkt, dass meine Lösung hier nicht gut ist, dann zögere bitte nicht, dies zu kommentieren und ich versuche es vollkommen richtig zu machen.

Joe

+0

Sehr hilfreich, danke. – zetetic

+0

Ihre Begrüßung, stimmen Sie einfach die Antworten ab! – TheDelChop

7

Mit der neuen RSpec Syntax, Stummel Sie eine Kette wie so

allow(@user).to receive_message_chain(:solutions, :find) 
# or 
allow_any_instance_of(User).to receive_message_chain(:solutions, :find)