Нужна помощь Rspec тест

Я пытаюсь изучить 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

Мой вопрос заключается в том, что когда я запускаю rspec на тесте PUT UPDATE, он не проходит. Но POST-тест пройден. Я понятия не имею, что происходит. Я использую Rails 3.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

person Zeck    schedule 01.11.2011    source источник
comment
Похоже, у вас нет модели статьи.   -  person megas    schedule 01.11.2011
comment
У меня есть модель статьи. Любая идея?   -  person Zeck    schedule 01.11.2011
comment
Когда я вхожу в функцию get_article, тип класса current_user.articles — Object. Это правильно?   -  person Zeck    schedule 01.11.2011
comment
Что произойдет, если вы свяжете :create вместо :build?   -  person Dave Newton    schedule 01.11.2011
comment
(Переходя к ответу; слишком долго.)   -  person Dave Newton    schedule 01.11.2011
comment
В чем проблема?   -  person Dave Newton    schedule 02.11.2011


Ответы (1)


Вот в чем дело.

Когда вы заглушаете, вы просто говорите «если вызывается эта цепочка методов, верните это». Есть две проблемы с этим. 1) код никогда не вызывает build и 2) нет фактических ассоциаций.

Я считаю, что вам нужно заглушить current_user.articles, чтобы вернуть коллекцию статей. Проблема в том, что ассоциации AR — это не массивы, а прокси.

См. это сообщение SO и это сообщение SO для получения более подробной информации. Обычный массив не будет обрабатывать метод find как метод AR, которым он действительно является, и вы не возвращаете ни одной статьи.

Поскольку у вас есть идентификатор статьи, вы можете просто вернуть эту конкретную статью, но ваша цель – вернуть эту статью из статей пользователя, чтобы избежать обновления чужих (я предполагаю, ).

Это сообщение SO также может помочь, и это.

Другими словами, вам может понадобиться реальный пользователь с реальными связанными объектами, поэтому такие вещи, как find, будут работать без взлома.

(Я полностью понимаю, что это не настоящий ответ; я никогда не делал этого с помощью заглушек, я использовал фабрики и т. д.)

person Dave Newton    schedule 01.11.2011