简体   繁体   中英

RSpec-rails | Description of Finding an Associated Model

How can I describe of finding an associated model in the RSpec-rails controller examples?

I try the following:

Article

class Article < ActiveRecord::Base
  has_many :comments
end

Comment

class Comment < ActiveRecord::Base
end

CommentsControllerSpec

describe CommentsController do
  describe 'update' do
    let(:article) { stub_model Article }
    let(:comment) { stub_model Comment }

    before { Article.stub(:find) { article } }
    before { article.stub(:comments) { [comment] } }

    it 'finds a comment' do
      article.comments.should_receive(:find) { comment }
      put :update, article_id: article.id, id: comment.id
    end
  end
end

CommentsController

class CommentsController < ApplicationController
  def update
    Article.find.comments.find
  end
end

But unfortunatelly it doesn't work. Any ideas?

Thanks.

I tackled the problem by myself.

Here's the approximate list of actions to describe of finding an associated model in the Rails' controllers.

1.

describe CommentsController do
  describe 'update' do
  end
end

2.

describe CommentsController do
  describe 'update' do
    it 'finds an article' # <=
  end
end

3.

describe CommentsController do
  describe 'update' do
    it 'finds an article' do
      Article.should_receive(:find) # <=
      put :update                   # <=
    end
  end
end

4.

No route matches {:controller=>"comments", :action=>"update"}

5.

describe CommentsController do
  describe 'update' do
    let(:article) { stub_model Article } # <=

    it 'finds a article' do
      Article.should_receive(:find)
      put :update, article_id: article.id # <=
    end
  end
end

6.

No route matches \
  {:article_id=>"1025", :controller=>"comments", :action=>"update"}

7.

describe CommentsController do
  describe 'update' do
    let(:article) { stub_model Article }
    let(:comment) { stub_model Comment } # <=

    it 'finds an article' do
      Article.should_receive(:find)
      put :update, article_id: article.id, id: comment.id # <=
    end
  end
end

8.

(<Article (class)>).find(any args)
       expected: 1 time
       received: 0 times

9.

class CommentsController < ApplicationController
  def update
    Article.find
  end
end

10.

Success!

11.

describe CommentsController do
  describe 'update' do
    let(:article) { stub_model Article }
    let(:comment) { stub_model Comment }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) # <=
      put :update, article_id: article.id, id: comment.id
    end
  end
end

12.

<Article (class)> received :find with unexpected arguments
  expected: ("1025")
       got: (no args)

13.

class CommentsController < ApplicationController
  def update
    Article.find(params[:article_id]) # <=
  end
end

14.

Success!

15.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {                                    # <=
      mock(ActiveRecord::Associations::HasManyAssociation) # <=
    }                                                      # <=

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s)
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do                               # <=
      article.stub(:comments) { association }             # <=
      association.should_receive(:find)                   # <=
      put :update, article_id: article.id, id: comment.id # <=
    end                                                   # <=
  end
end

16.

Couldn't find Article with id=1027

17.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      mock(ActiveRecord::Associations::HasManyAssociation)
    }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s)
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article } # <=
      article.stub(:comments) { association }
      association.should_receive(:find)
      put :update, article_id: article.id, id: comment.id
    end
  end
end

18.

(Mock ActiveRecord::Associations::HasManyAssociation).find(any args)
    expected: 1 time
    received: 0 times

19.

class CommentsController < ApplicationController
  def update
    Article.find(params[:article_id]).comments.find # <=
  end
end

20.

update
  finds an article (fail!)
  finds a comment  (success!)

undefined method `comments' for nil:NilClass

21.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      mock(ActiveRecord::Associations::HasManyAssociation)
    }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article } # <=
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      article.stub(:comments) { association }
      association.should_receive(:find)
      put :update, article_id: article.id, id: comment.id
    end
  end
end

22.

update
  finds an article (fail!)
  finds a comment  (success!)

Couldn't find Comment without an ID

23.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      mock(ActiveRecord::Associations::HasManyAssociation)
    }

    before { article.stub(:comments) { association } } # <=

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article }
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      # -> article.stub(:comments) { association } <-
      association.should_receive(:find)
      put :update, article_id: article.id, id: comment.id
    end
  end
end

24.

update
  finds an article (fail!)
  finds a comment  (success!)

Mock ActiveRecord::Associations::HasManyAssociation \
  received unexpected message :find with (no args)

25.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      mock(ActiveRecord::Associations::HasManyAssociation).as_null_object # <=
    }

    before { article.stub(:comments) { association } }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article }
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      association.should_receive(:find)
      put :update, article_id: article.id, id: comment.id
    end
  end
end

26.

Success!

27.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      mock(ActiveRecord::Associations::HasManyAssociation).as_null_object
    }

    before { article.stub(:comments) { association } }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article }
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      association.should_receive(:find).with(comment.id.to_s) # <=
      put :update, article_id: article.id, id: comment.id
    end
  end
end

28.

Mock ActiveRecord::Associations::HasManyAssociation \
  received :find with unexpected arguments
  expected: ("1028")
       got: (no args)

29.

class CommentsController < ApplicationController
  def update
    Article.find(params[:article_id]).comments.find(params[:id]) # <=
  end
end

30.

Success!

31.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      double(ActiveRecord::Associations::HasManyAssociation).as_null_object # <=
    }

    before { article.stub(:comments) { association } }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article }
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      association.should_receive(:find).with(comment.id.to_s)
      put :update, article_id: article.id, id: comment.id
    end

    it 'assigns @comment' do                              # <=
      Article.stub(:find) { article }                     # <=
      association.stub(:find) { comment }                 # <=
      put :update, article_id: article.id, id: comment.id # <=
      assigns[:comment].should eq comment                 # <=
    end                                                   # <=
  end
end

32.

expected: #<Comment >
     got: nil

33.

class CommentsController < ApplicationController
  def update
    @comment = Article.find(params[:article_id]).comments.find(params[:id]) # <=
  end
end

34.

Success!

35.

describe CommentsController do
  describe 'update' do
    let(:article)     { stub_model Article }
    let(:comment)     { stub_model Comment }
    let(:association) {
      double(ActiveRecord::Associations::HasManyAssociation).as_null_object
    }

    before { article.stub(:comments) { association } }

    it 'finds an article' do
      Article.should_receive(:find).with(article.id.to_s) { article }
      put :update, article_id: article.id, id: comment.id
    end

    it 'finds a comment' do
      Article.stub(:find) { article }
      association.should_receive(:find).with(comment.id.to_s)
      put :update, article_id: article.id, id: comment.id
    end

    it 'assigns @article' do                              # <=
      Article.stub(:find) { article }                     # <=
      put :update, article_id: article.id, id: comment.id # <=
      assigns[:article].should eq article                 # <=
    end                                                   # <=

    it 'assigns @comment' do
      Article.stub(:find) { article }
      association.stub(:find) { comment }
      put :update, article_id: article.id, id: comment.id
      assigns[:comment].should eq comment
    end
  end
end

36.

expected: #<Article >
     got: nil

37.

class CommentsController < ApplicationController
  def update
    @article = Article.find(params[:article_id])   # <=
    @comment = @article.comments.find(params[:id]) # <=
  end
end

38.

Success!

39.

class CommentsController < ApplicationController
  before_filter :find_article, only: :update # <=
  before_filter :find_comment, only: :update # <=

  def update
    # -> @article = Article.find(params[:article_id])   <-
    # -> @comment = @article.comments.find(params[:id]) <-
  end

  private                                          # <=
    def find_article                               # <=
      @article = Article.find(params[:article_id]) # <=
    end                                            # <=

    def find_comment                                 # <=
      @comment = @article.comments.find(params[:id]) # <=
    end                                              # <=
end

40.

Success!

I'd say, replace:

before { article.stub(:comments) { [comment] } }

With:

before { article.stub_chain(:comments, :find) { [comment] } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM