2015-10-01 53 views
1

我有一個簡單的MySQL包裝類,它將運行查詢並返回結果。Rspec:允許和allow_any_instance_of之間的區別

class Rsql 
    def initialize(db) 
    @client = Mysql2::Client 
    @db = db 
    end 

    def execute_query() 
    client = @client.new(@db) 
    client.query("select 1") 
    end 

end 

我想測試一些涉及查詢結果的東西,但我不想實際連接到數據庫來獲得結果。我試過這個測試,但不起作用:

RSpec.describe Rsql do 

    it "does it" do 
    mock_database = double 
    rsql = Rsql.new(mock_database) 

    mock_mysql_client = double 
    allow(mock_mysql_client).to receive(:query).and_return({"1" => 1}) 

    allow_any_instance_of(Mysql2::Client).to receive(:new).and_return(mock_mysql_client) 
    expect(rsql.execute_query).to eq({"1" => 1}) 
    end 

end 

用「allow」替換「allow_any_instance_of」的作品。我的印象是,allow_any_instance_of()是某種全局的「假設這個類在整個程序中以這種方式運行」,而allow()則是針對某個類的特定實例。

有人可以向我解釋這種行爲嗎?我是新來的Rspec,所以我很抱歉,如果這個答案是明顯的。我試圖尋找答案,但我無法拿出正確的搜索字符串來找到答案。也許我不知道什麼時候發現它。

謝謝!

回答

1

從RSpec 3.3開始,any_instance已棄用,建議不要在測試中使用。

From the docs

any_instance是存根或嘲笑的一類 的任何實例舊的方式,但進行的所有類全球猴子補丁的行李。注意我們通常建議不要使用此功能的 。

您應該只需要使用allow(some_obj),文檔中有一些很好的示例(請參閱here)。

如:

RSpec.describe "receive_messages" do 
    it "configures return values for the provided messages" do 
    dbl = double("Some Collaborator") 
    allow(dbl).to receive_messages(:foo => 2, :bar => 3) 
    expect(dbl.foo).to eq(2) 
    expect(dbl.bar).to eq(3) 
    end 
end 

編輯,如果你真的想用any_instance,這樣做是這樣的:

(Mysql2::Client).allow_any_instance.to receive(:something) 
+0

我知道我應該憑藉的事實,即使用允許() allow_any_instance_of實際上不起作用。我的問題更多的是「爲什麼允許()工作」?我看到的每個示例allow()都涉及聲明一個模擬對象,然後允許該模擬對象接收和返回東西。我使用它的方式涉及允許任何對Mysql2 :: Client.new()方法的調用返回一個模擬對象。然後我允許,ock對象的query()方法返回東西。爲什麼我不允許Mysql2 :: Client.query()在沒有這個額外步驟的情況下返回我想要的東西? –

+0

更新了一個例子 – Anthony

+0

我沒有綁定使用allow_any_instance。如果他們說不使用它,我不會使用它。我只是想知道爲什麼它不按我嘗試使用它的方式工作。 在任何情況下,我都能夠讓allow()工作,並且我認爲我很好地處理了如何模擬對象和存根方法(以及實際的非模擬對象)。不過,感謝您的幫助。 –