开发者

RSpec Mocks Question for ActiveRecord Find First with Where

I am trying to sort out my RSpec tests for a controller of mine, but its not working and I need some help figuring it out.

My Rspec is:

  before(:each) do
    @topic = mock_model(Topic, :update_attributes => true)
    Topic.stub!(:where).with({:slug=>"some-slug"}).and_return(@topic)
    with_valid_user
  end

  it "should find topic and return object" do
    Topic.should_receive(:where).with("some-slug").and_return(@topic)
    put :update, :topic_slug => "some-slug", :topic => {}
  end

The controller logic I am trying to test is:

  def get_topic
    @topic = Topic.where(:slug => params[:topic_slug]).first
    @topic
  end

But the output I am getting is:

 Failure/Error: Topic.stub!(:where).with({:slug=>"some-slug"}).first.and_return(@topic)
 NoMethodError:
   undefined method `first' for #<RSpec::Mocks::MessageExpectation:0x104c99910>
 # ./spec/c开发者_StackOverflow社区ontrollers/topics_controller_spec.rb:41

Obviously, it seems like the method call for "first". I understand is a bit redundant in this particular case, so I could remove it, but rather than hack around a hole in my knowledge, I'd like to learn how to do it properly (for this scenario).

Can anyone help me fill my hole?

Update:

I added the [@topic] array as suggested in the answers, but now I am getting the error:

  Failure/Error: put :update, :topic_slug => "some-slug", :topic => {}
       Mock "Topic_1001" received unexpected message :slug with (no args)

With respect to this code:

  def get_topic
    @topic = Topic.where(:slug => params[:topic_slug]).first
    @topic
  end

The parameters can't be changed (at least not trivially). Further assistance greatly appreciated!


Change this line

Topic.should_receive(:where).with("some-slug").and_return(@topic)

to this

Topic.should_receive(:where).with("some-slug").and_return([@topic])

you expect array but return one element.


stub_chain is a code smell and should be treated as a last resort. It ties your spec very tightly to implementation detail, which is subject to change via refactoring.

I'd recommend something like this:

Topic.should_receive(:with_slug).and_return(@topic)

Then add a with_slug method to Topic and you're good to go.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜