2011-11-01 128 views
0

我在學習RSpec併爲CRUD操作編寫測試。這裏是我的控制器:需要幫助Rspec測試

class ArticlesController < ApplicationController 

    respond_to :html, :json 

    before_filter :authenticate_user! 

    # GET /articles 
    # GET /articles.json 
    def index 
    @articles = current_user.articles.all 
    respond_with(@articles) 
    end 

    # GET /articles/1 
    # GET /articles/1.json 
    def show 
    @article = current_user.articles.find(params[:id]) 
    respond_with @article 
    end 

    # GET /articles/new 
    # GET /articles/new.json 
    def new 
    @article = current_user.articles.build 
    respond_with @article 
    end 

    # GET /articles/1/edit 
    def edit 
    @article = get_article(params[:id]) 
    end 

    # POST /articles 
    # POST /articles.json 
    def create 
    @article = current_user.articles.build(params[:article]) 
    flash[:notice] = "Article was successfully created!" if @article.save 
    respond_with(@article, location: articles_path) 
    end 

    # PUT /articles/1 
    # PUT /articles/1.json 
    def update 
    @article = get_article(params[:id]) 
    if @article.update_attributes(params[:article]) 
     flash[:notice] = "Article was successfully updated." 
    end 
    respond_with @article 
    end 

    # DELETE /articles/1 
    # DELETE /articles/1.json 
    def destroy 
    @article = get_article(params[:id]) 
    @article.destroy 
    respond_with @article 
    end 

    private 
    def get_article(article_id) 
    current_user.articles.find(article_id) 
    end 
end 

而我的文章rspec的:

describe ArticlesController do 

    def valid_attributes 
    { 
     :title => "Introducting Node.js", 
     :content => "Node.js is an event-driven...." 
    } 
    end 

    let(:article) do 
    build(:article, valid_attributes) 
    end 

    describe "PUT 'update'" do 

    before(:each) do 
     controller.stub_chain(:current_user, :articles, :build) { article } 
    end 

    context "success" do 
     before(:each) do 
     article.should_receive(:update_attributes).and_return(true) 
     put :update, id: article.id 
     end 

     it "sets notice" do 
     flash[:notice].should eq("Article was successfully updated!") 
     end 
    end 
    end 

    describe "POST 'create'" do 

    before(:each) do 
     controller.stub_chain(:current_user, :articles, :build) { article } 
    end 

    context "success" do 
     before(:each) do 
     article.should_receive(:save).and_return(true) 
     post :create 
     end 

     it "sets notice" do 
     flash[:notice].should eq("Article was successfully created!") 
     end 

     it "should redirect to article path" do 
     response.should redirect_to(articles_path) 
     end 
    end 

    context "failure" do 
     before(:each) do 
     article.should_receive(:save).and_return(false).as_null_object 
     post :create 
     end 

     it "assigns @article" do 
     assigns(:article).should == article 
     end 
    end 
    end 
end 

我的問題是,當我運行PUT更新測試RSpec的失敗。但POST測試已通過。我不知道發生了什麼事。我正在使用帶有omniauth的Rails 3.1.1。我沒有使用Devise。這是測試結果。爲什麼?請幫幫我嗎?

Failures: 

    1) ArticlesController PUT 'update' success sets notice 
    Failure/Error: put :update, id: article.id 
    NoMethodError: 
     undefined method `find' for #<Object:0xa3cfd20> 
    # ./app/controllers/articles_controller.rb:61:in `get_article' 
    # ./app/controllers/articles_controller.rb:44:in `update' 
    # ./spec/controllers/articles_controller_spec.rb:46:in `block (4 levels) in <top (required)>' 

Finished in 24.09 seconds 
5 examples, 1 failure 
+0

它看起來像你沒有Article模型。 – megas

+0

我有一個文章模型。任何想法? – Zeck

+0

當我登錄get_article函數的current_user.articles類類型爲Object時。這是對的嗎? – Zeck

回答

2

這是事情。

當你存根時,你只是說「如果這個方法鏈被調用,返回這個。」這有兩個問題。 1)代碼永遠不會調用build,並且2)沒有實際的關聯。

我相信你需要存根current_user.articles才能返回文章集合。問題是AR關聯不是實際的數組,而是代理。

有關更多詳細信息,請參見this SO postthis SO post。常規數組不會將find方法看作是真正的AR方法,並且您不會返回單個文章。

既然你文章ID,您可以只是返回特定的文章,但你的目標是從用戶的文章中返回的文章,以避免更新別人的(我認爲)。

This SO post也可能有幫助,和this

換句話說,你可能想要一個真正的用戶,並有真正的關聯對象,所以諸如find之類的東西將不會工作。

(我充分認識到這不是一個真正的答案,我從來沒有通過磕碰這樣做,我用工廠的/ etc。)