我有一个简单的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
我想测试一些涉及查询结果的东西,但我不想实际连接到数据库来获得结果。我尝试过这个测试,但它不起作用:
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_any_instance_of”替换为“allow”有效。我的印象是allow_any_instance_of()是某种全局“假装这个类在整个程序中以这种方式运行”,而allow()是针对类的特定实例。
有人可以向我解释这种行为吗?我是Rspec的新手,所以如果这个答案显而易见,我会道歉。我试着寻找答案,但我找不到合适的搜索字符串来找到答案。也许我不知道什么时候能找到它。
谢谢!
答案 0 :(得分:2)
自RSpec 3.3起,any_instance
已弃用,建议不要在测试中使用。
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)