【问题标题】:RSpec - How to mock a stored procedureRSpec - 如何模拟存储过程
【发布时间】:2012-12-10 23:30:43
【问题描述】:

考虑以下stored procedure

CREATE OR REPLACE FUNCTION get_supported_locales()
RETURNS TABLE(
  code character varying(10)
) AS
...

调用它的方法如下:

def self.supported_locales
  query = "SELECT code FROM get_supported_locales();"
  res = ActiveRecord::Base.connection.execute(query)
  res.values.flatten
end

我正在尝试为此方法编写测试,但在模拟时遇到了一些问题:

it "should list an intersection of locales available on the app and on last fm" do
  res = mock(PG::Result)
  res.should_receive(:values).and_return(['en', 'pt'])
  ActiveRecord::Base.connection.stub(:execute).and_return(res)

  Language.supported_locales.should =~ ['pt', 'en']
end

此测试成功,但在此之后运行的任何测试都会显示以下消息:

WARNING:  there is already a transaction in progress

为什么会这样?我在嘲讽吗

数据库是postgres 9.1。

【问题讨论】:

    标签: ruby postgresql rspec mocking


    【解决方案1】:

    您的测试正在使用数据库级事务运行。测试完成后,事务将回滚,因此测试中所做的任何更改都不会实际保存到数据库中。在您的情况下,不会发生此回滚,因为您已在 ActiveRecord 连接上存根执行方法。

    您可以全局禁用事务并切换到使用DatabaseCleaner 来启用/禁用各种测试的事务。然后,您可以设置默认通过 DatabaseCleaner 使用事务,这样您现有的测试就不会改变,然后在这个测试中选择禁用事务以支持其他策略(例如 null 策略,因为没有清理要为此测试完成)。

    This other SO post 表示您可以避免全局禁用事务并在每个测试的基础上关闭它们,不过我自己没有尝试过。

    【讨论】:

    • 我最终取消了 ActiveRecord ActiveRecord::Base.connection.rspec_reset
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    相关资源
    最近更新 更多