4

因此,我正在为一种方法编写测试,该方法出于性能原因应该在不使用 SQL 查询的情况下实现它需要实现的目标。我在想我需要知道的就是存根:

describe SomeModel do
  describe 'a_getter_method' do
    it 'should not touch the database' do
      thing = SomeModel.create

      something_inside_rails.should_not_receive(:a_method_querying_the_database)

      thing.a_getter_method
    end
  end
end

编辑:提供一个更具体的例子:

class Publication << ActiveRecord::Base
end
class Book << Publication
end
class Magazine << Publication
end

class Student << ActiveRecord::Base
  has_many :publications

  def publications_of_type(type)
    #this is the method I am trying to test.  
    #The test should show that when I do the following, the database is queried.

    self.publications.find_all_by_type(type)
  end
end


describe Student do
  describe "publications_of_type" do
    it 'should not touch the database' do
       Student.create()
       student = Student.first(:include => :publications)
       #the publications relationship is already loaded, so no need to touch the DB

       lambda {
         student.publications_of_type(:magazine)
       }.should_not touch_the_database
    end
  end
end

所以在这个例子中测试应该失败,因为 rails 'find_all_by' 方法依赖于 SQL。

4

5 回答 5

7

SomeModel.should_not_receive(:connection)应该这样做。

于 2012-11-16T14:24:30.147 回答
1

我知道这个问题现在已经很老了,但我偶然发现它试图做同样的事情。在环顾四周后,我发现有一个伟大而简单的宝石。

https://github.com/brigade/db-query-matchers

它添加了一个带块的 rspec 匹配器,因此您可以使用:

expect { subject.make_no_queries }.to_not make_database_queries

配置也非常简单,这意味着您可以将一些确实进行查询的调用与连接到数据库的调用子集混合在一起。

于 2016-12-12T21:29:35.967 回答
0

SomeModel.create创建一个实例SomeModel并将其保存到数据库中,并返回创建的对象。

您想确保任何getter 方法都不会访问数据库吗?在 Rails 中,只有检索关联才会访问数据库,并且仅在第一次调用它们时。

如果您有一个 getter 方法的特定实现,您“怀疑”它会访问数据库,我会假设它很容易测试,或者您是否正在防止未来的实现?

也许最简单的方法是做SomeModel.build,然后执行你的测试。创建一个实例,而不将其build保存到数据库中。如果 getter 工作,它肯定没有命中数据库(因为什么都不应该存在——取决于你的代码——如果不知道你实际测试的是什么 getter,很难说)。

如果您正在测试特定的 getter 方法,并且想要更相关的答案,请提供一些代码。

于 2012-11-16T14:15:15.890 回答
0

我还没有足够的积分来发表评论,但要跟进@histocrat 留下的答案,以及@will-tomlins 留下的评论。如果你用存根ActiveRecord::Base.connection代替SomeModel.connection你将避免得到“堆栈级别太深”的消息,而是从匹配器本身得到一个错误。

于 2020-05-31T16:05:15.103 回答
0

称呼

ActiveRecord::Base.connection.disconnect!

在调用该方法之前,检查是否没有引发错误。

于 2021-11-03T08:42:17.400 回答