简体   繁体   English

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

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

So I'm writing a test for a method which for performance reasons should achieve what it needs to achieve without using SQL queries.因此,我正在为一种方法编写测试,该方法出于性能原因应该在不使用 SQL 查询的情况下实现它需要实现的目标。 I'm thinking all I need to know is what to stub:我在想我需要知道的只是存根:

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

EDIT : to provide a more specific example:编辑:提供一个更具体的例子:

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

So the test should fail in this example, because the rails 'find_all_by' method relies on SQL.所以在这个例子中测试应该失败,因为 rails 'find_all_by' 方法依赖于 SQL。

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

I know this question is super old now, but I stumbled across it trying to do the same thing.我知道这个问题现在已经很老了,但我在尝试做同样的事情时偶然发现了它。 After looking around some more I've found there's a great and simple gem for this.环顾四周后,我发现有一个伟大而简单的宝石。

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

It adds an rspec matcher that takes a block so you can just use:它添加了一个带有块的 rspec 匹配器,因此您可以使用:

expect { subject.make_no_queries }.to_not make_database_queries

The configuration is super simple too, and it means you can have some calls that do make queries mixed in with a subset of calls that do connect to the database.配置也非常简单,这意味着您可以将一些调用与连接到数据库的调用的子集混合在一起。

SomeModel.create creates the an instance of SomeModel and saves it to the database, and returns the created object. SomeModel.create创建的一个实例SomeModel并将其保存到数据库中,并返回创建的对象。

Do you want to make sure that any getter method does not acces the database?您想确保任何getter 方法都不会访问数据库吗? In rails only retrieving associations will hit the database, and only the first time they are called.在 rails 中,只有检索关联才会访问数据库,并且只有在第一次调用它们时才会访问。

If you have a specific implementation of a getter method, which you "suspect" would hit the database, I would assume it would be easy to test, or are you protecting against future implementations?如果你有一个 getter 方法的特定实现,你“怀疑”会影响数据库,我认为它很容易测试,或者你是否在防止将来的实现?

Maybe the easiest way would be to do SomeModel.build , and then perform your test.也许最简单的方法是做SomeModel.build ,然后执行你的测试。 The build creates an instance, without saving it to the database. build会创建一个实例,但不会将其保存到数据库中。 If the getter works, it sure didn't hit the database (since nothing should be there ---depending on your code --a bit hard to say without any clue what getter you are actually testing).如果 getter 有效,它肯定没有访问数据库(因为那里不应该有任何东西——取决于你的代码——有点难说,不知道你实际测试的是什么 getter)。

If you are testing a specific getter method, and want more relevant answer, please provide some code.如果您正在测试特定的 getter 方法,并希望获得更多相关答案,请提供一些代码。

I don't have enough points yet to comment, but following up on the answer left by @histocrat, and the comment left by @will-tomlins.我还没有足够的点数来评论,但要跟进@histocrat 留下的答案,以及@will-tomlins 留下的评论。 If you stub ActiveRecord::Base.connection in place of the SomeModel.connection you will avoid getting the 'stack level too deep' message, and instead get an error from the matcher itself.如果您存根ActiveRecord::Base.connection代替SomeModel.connection您将避免收到“堆栈级别太深”消息,而是从匹配器本身获取错误。

Call称呼

ActiveRecord::Base.connection.disconnect!

before calling the method, and check if there was no error raised.在调用该方法之前,并检查是否没有引发错误。

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

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