【问题标题】:Rspec testing ordered retrieval from a scoped method of model using mocking and expectationsRspec 使用模拟和期望从模型的范围方法中测试有序检索
【发布时间】:2013-02-28 16:31:37
【问题描述】:

我是 rspec、模拟和存根的新手。我开始慢慢地开始欣赏和理解隔离测试和模拟/存根的概念。我有一个基本问题,我认为通过代码更容易解​​释:

class NewsItem < ActiveRecord::Base
  ...
  scope :ordered, order("created_at DESC")
  ...
end

现在在我的模型测试中,我希望测试返回 news_items 有序列表的行为。使用 FactoryGirl DB-touching 测试,我实现了如下:

# TODO use mocking and stubbing here
it "should have an ordered method to retrieve news items in the descending order" do
  news_item_x = create(:news_item, created_at: DateTime.new(2012,01,01))
  news_item_y= create(:news_item, created_at: DateTime.new(2011,01,01))
  news_item_z= create(:news_item, created_at: DateTime.new(2012,03,01))

  # .all added to avoid comparison failure between groups of NewsItem objects an ActiveRel group.
  expect(NewsItem.ordered.all).to eql([news_item_z, news_item_x, news_item_y])
end 

我不知道如何将上述测试转换为模拟和存根。这是第一次尝试,但显然我在这里误解了一些核心概念。

xit "should have an ordered method to retrieve news items in the descending order" do

  news_item_x = mock(NewsItem, created_at: DateTime.new(2012,01,01))
  news_item_y = mock(NewsItem, created_at: DateTime.new(2011,01,01))
  news_item_z = mock(NewsItem, created_at: DateTime.new(2012,03,01))

  NewsItem.should_receive(:ordered).and_return([news_item_z, news_item_x, news_item_y])
  # NewsItem.should_receive(:ordered).ordered # not working.

  # this is pointless as it's not checking the order of anything, just the call.
  NewsItem.ordered
end 

模拟/存根在这种测试中是否合适?

任何建议将不胜感激。

结论:

我从@arieljuod 和@zetetic 那里得到了一些很好的答案。对于我最初的问题,在这里嘲笑和存根是否合适?正如@zetetic 指出的那样,答案似乎是否定的。

另一方面,@arieljuod 提供了一种非常好的方法来实际测试我的代码 sn-p(不一定通过模拟和存根)。这两个都是有效的答案。

【问题讨论】:

    标签: rspec mocking rspec-rails stubbing


    【解决方案1】:

    模拟/存根在这种测试中是否合适?

    没有。

    使用模拟和存根的目的是将编写的代码与其依赖项隔离开来。在scope 的情况下,它所依赖的所有东西都埋在Rails 框架中。此外,您不需要首先测试框架/库代码的内部结构——原作者已经这样做了。

    【讨论】:

      【解决方案2】:

      您应该只测试您的“有序”作用域在以“created_at DESC”作为参数的模型上调用“订单”,至少在那个简单的例子中是这样

      describe 'ordered' do
        it 'orders by created_at desc' do
          NewsItem.should_receive(:order).once.with('created_at DESC')
          NewsItem.ordered
        end
      end
      

      您可以相信查询将具有您想要的顺序

      更复杂的范围可能需要其他规范,但您始终可以在更小的范围内打破复杂范围以正确测试它们,并且仅在范围内执行真正的数据库查询(就像您首先实际创建对象并运行查询一样不是微不足道的(如果您执行某种奇怪的手动 sql 查询,您应该测试它是否符合您的要求,否则,请信任 rails)

      编辑:如 cmets 所述,该代码不起作用,您可以检查 ActiveRelation 对象是否具有所需的顺序集:

      describe 'ordered' do
        it 'orders by created_at desc' do
          NewsItem.ordered.order_values.should == ['created_at DESC']
        end
      end
      

      这样您就知道活动关系将在查询中使用该顺序

      【讨论】:

      • 我理解您回答背后的理论,但是当我实际尝试时,我在通话中遇到了错误。确切的错误是:Failure/Error: NewsItem.should_receive(:order).with("created_at DESC") ().order("created_at DESC") 预期:1 次收到:0 次。 .should_receive(:order) 部分中的期望语法是否存在问题?
      • 我错了,在 ActiveRelation 对象上调用 order 方法。检查我的编辑
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      相关资源
      最近更新 更多