繁体   English   中英

使用Rails和Rspec,你如何测试数据库没有被某个方法触及

[英]Using Rails and Rspec, how do you test that the database is not touched by a method

因此,我正在为一种方法编写测试,该方法出于性能原因应该在不使用 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。

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

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

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

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

expect { subject.make_no_queries }.to_not make_database_queries

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

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

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

如果你有一个 getter 方法的特定实现,你“怀疑”会影响数据库,我认为它很容易测试,或者你是否在防止将来的实现?

也许最简单的方法是做SomeModel.build ,然后执行你的测试。 build会创建一个实例,但不会将其保存到数据库中。 如果 getter 有效,它肯定没有访问数据库(因为那里不应该有任何东西——取决于你的代码——有点难说,不知道你实际测试的是什么 getter)。

如果您正在测试特定的 getter 方法,并希望获得更多相关答案,请提供一些代码。

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

称呼

ActiveRecord::Base.connection.disconnect!

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM