0

RSpecを学び、CRUDアクションのテストを作成しようとしています。これが私のコントローラーです:

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

私の質問は、PUTUPDATEでrspecを実行するとテストが失敗することです。しかし、POSTテストは合格です。何が起こっているのかわかりません。Rails3.1.1をomniauthで使用しています。私は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
4

1 に答える 1

2

つまりね。

スタブしているときは、「このメソッドチェーンが呼び出されたら、これを返します」と言っているだけです。それには2つの問題があります。1)コードが呼び出すことはなくbuild、2)実際の関連付けはありません。

current_user.articles記事のコレクションを返すには、スタブする必要があると思います。問題は、ARアソシエーションが実際の配列ではなく、プロキシであるということです。

詳細については、このSO投稿このSO投稿を参照してください。通常の配列は、findメソッドを実際のARメソッドのように処理せず、単一の記事を返しません。

記事IDを持っているので、その特定の記事を返すこともできますが、他の人の記事を更新しないように、ユーザーの記事内からその記事を返すことが目標です(私は推測します)。

このSO投稿も役立つかもしれません、そしてこれ

言い換えれば、実際に関連付けられたオブジェクトを持つ実際のユーザーが必要な場合があるため、findハッカリーなしで機能するようになります。

(私はこれが本当の答えではないことを完全に認識しています。私はスタブを介してこれを行ったことがなく、工場などを使用しました。)

于 2011-11-01T00:36:27.653 に答える