Rspec使用模拟和期望测试从模型的作用域方法进行有序检索

Rspec使用模拟和期望测试从模型的作用域方法进行有序检索,rspec,mocking,rspec-rails,stubbing,Rspec,Mocking,Rspec Rails,Stubbing,我是rspec的新手,嘲笑和嘲弄。我慢慢地开始理解和理解孤立测试和模拟/存根的概念。我有一个基本问题,我认为通过代码更容易解释: class NewsItem < ActiveRecord::Base ... scope :ordered, order("created_at DESC") ... end 我无法理解如何将上述测试转换为模拟和存根。这是第一次尝试,但显然我误解了一些核心概念 xit "should have an ordered method to retri

我是rspec的新手,嘲笑和嘲弄。我慢慢地开始理解和理解孤立测试和模拟/存根的概念。我有一个基本问题,我认为通过代码更容易解释:

class NewsItem < ActiveRecord::Base
  ...
  scope :ordered, order("created_at DESC")
  ...
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和@Zettetic那里得到了一些很好的答案。对于我最初的问题,嘲弄和存根在这里合适吗?正如@zettetic所指出的,答案似乎是否定的

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

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

没有

使用mock和stub的目的是将您编写的代码与其依赖项隔离开来。在
范围
的情况下,它所依赖的一切都隐藏在Rails框架中。此外,您不需要首先测试框架/库代码的内部结构——最初的作者已经这样做了。

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

没有


使用mock和stub的目的是将您编写的代码与其依赖项隔离开来。在
范围
的情况下,它所依赖的一切都隐藏在Rails框架中。此外,您不需要首先测试框架/库代码的内部结构——最初的作者已经这样做了。

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

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)

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

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

这样,您就知道活动关系将在查询中使用该顺序,您应该只测试您的“ordered”作用域是否在以“created_at DESC”为参数的模型上调用“order”,至少在这个简单的示例中是这样的

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)

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

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

这样,您就知道active relation将在查询中使用该顺序

我理解您答案背后的原理,但当我实际尝试时,我在通话中遇到了一个错误。确切的错误是:失败/错误:新闻项。应接收(:order)。with(“created_at DESC”)()。order(“created_at DESC”)预期:1次接收:0次。此处的预期语法是否与.should_receive(:order)中的预期语法有问题part?我错了,order方法是在ActiveRelation对象上调用的。检查我的编辑我理解你答案背后的原理,但当我实际尝试时,我在调用中遇到了一个错误。确切的错误是:失败/错误:NewsItem.when_receive(:order)。with(“created_at DESC”)()。order(“created_at DESC”)预期:1次接收:0次。此处的预期语法是否存在问题?是否应接收(:order)部分?我错了,对ActiveRelation对象调用了order方法。请检查我的编辑