RSpec 模拟 ActiveRecord Find First 与Where 的问题

发布于 2024-11-28 20:44:33 字数 1412 浏览 0 评论 0原文

我正在尝试整理我的控制器的 RSpec 测试,但它不起作用,我需要一些帮助来解决它。

我的 Rspec 是:

  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

我试图测试的控制器逻辑是:

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

但我得到的输出是:

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

显然,这似乎是“first”的方法调用。我知道在这种特殊情况下有点多余,所以我可以删除它,但我不想绕过我知识中的漏洞,而是想学习如何正确地做到这一点(对于这种情况)。

谁能帮我填补我的坑吗?

更新:

我按照答案中的建议添加了 [@topic] 数组,但现在我收到错误:

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

关于此代码:

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

参数无法更改(至少不能更改)。非常感谢进一步的帮助!

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/controllers/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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

§对你不离不弃 2024-12-05 20:44:33

将此行

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

更改为

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

你期望数组但返回一个元素。

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.

夜唯美灬不弃 2024-12-05 20:44:33

stub_chain 是一种代码味道,应该被视为最后的手段。它将您的规范与实现细节紧密联系在一起,而实现细节可能会通过重构而发生变化。

我建议这样:

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

然后向 Topic 添加一个 with_slug 方法,然后就可以开始了。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文