簡體   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