Rspec:allow和allow_any_instance_of之间的区别

Pau*_*ger 7 ruby rspec

我有一个简单的MySQL包装器类,它将运行查询并返回结果。

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

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

end
Run Code Online (Sandbox Code Playgroud)

我想测试一些涉及查询结果的内容,但我不想实际连接到数据库以获取结果。我尝试了此测试,但无法正常工作:

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
Run Code Online (Sandbox Code Playgroud)

allow_any_instance_of()allow()作品代替。我给人的印象allow_any_instance_of()是某种全局的“假装该类在整个程序中以这种方式表现”,而allow()针对某个类的特定实例。

有人可以向我解释这种行为吗?我是Rspec的新手,所以很抱歉这个答案很明显。我尝试搜索答案,但无法找到正确的搜索字符串。也许我不知道何时找到它。

Ant*_*ony 6

从 RSpec 3.3 开始,any_instance已弃用,不建议在您的测试中使用。

从文档

any_instance 是对类的任何实例进行存根或模拟的旧方法,但在所有类上都带有全局猴子补丁的包袱。请注意,我们通常建议不要使用此功能。

您应该只需要继续使用allow(some_obj),并且文档中有一些很好的示例(请参阅此处)。

如:

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
Run Code Online (Sandbox Code Playgroud)

编辑,如果你真的想使用 any_instance,这样做:

(Mysql2::Client).allow_any_instance.to receive(:something)
Run Code Online (Sandbox Code Playgroud)

Edit2,您的确切存根不起作用,因为您没有存根实例,而是在对象初始化之前存根。在那种情况下,你会这样做allow(Mysql2::Client).to receive(:new)