ruby-on-rails – Rspec:如何测试ActiveRecord :: Base.connection.execute

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Rspec:如何测试ActiveRecord :: Base.connection.execute前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用原始/裸机sql插件来提高我的服务的写入性能.我的模块里有这样的东西 –
insert = "('#{id}','#{status}','#{some_time_val}')"
sql_string = "INSERT INTO history ('device_id','status','time') VALUES #{insert}"
ActiveRecord::Base.connection.execute sql_string

当我写下面的rspec时,除了插入是否通过外,它还会测试所有内容.所以我的期望永远不会有效,因为rspec,database_cleaner等做回滚和交易的方式.
我试过用

self.use_transactional_fixtures = false

before(:all) do
    DatabaseCleaner.strategy = nil
  end

但插入仍然没有进入我的测试数据库

describe Worker do
  let (:device1) {FactoryGirl.create(:device)}
  let (:device2) {FactoryGirl.create(:device)}
  let (:device3) {FactoryGirl.create(:device)}
  self.use_transactional_fixtures = false

  before(:all) do
    DatabaseCleaner.strategy = nil
  end

  it "does something" do
    devices = [{"status" => "Offline","time" => "2013-09-17 18:17:17","id" => device1.id},{"status" => "Online","time" => "2013-09-17 18:18:18","id" => device2.id}]
    Worker.any_instance.stubs(:devices).returns(devices) ## Not important for this question
    Worker.new.perform

    device1.reload.status.should == "Offline" # FAILS
  end

end

我该如何测试?测试这样的原始sql插件有什么好策略?

解决方法

关于如何正确测试代码有两种思路:“方法”视角是关于确保自己的正确行为,“结果”视角有利于检查结果.我将提供两种观点.

方法

您没有编写ActiveRecord :: Base.connection.execute,并且您不对其正常工作负责.那么,您的测试可以专注于您传递给execute方法内容.那么,匹配的规范可能看起来像这样.

connection = double("Connection")
expect(ActiveRecord::Base).to receive(:connection) { connection }
expect(connection).to receive(:execute).with("...")
Worker.new.perform

where …是您要生成sql.根据您的喜好,验证sql是否正常工作可能会在其他地方完成,或者根本不会完成.这可以向您(以及将来的开发人员)保证已将正确的指令传送到您的数据库.

结果:

这种方法没有找到保证采取何种方法,它在结果中找到了保证.这是您在上述示例中采用的方法.

您没有告诉我们上面的执行方法是什么样的,所以我们不确定您的实现代码是否存在问题,而不是您用来提示ActiveRecord注意到您的更改的重新加载机制. ActiveRecord具有各种性能增强功能,旨在通过云直接绑定数据库内容与您在Ruby VM对象图中可以访问的内容.如果您愿意,可以尝试覆盖此行为,但如果您满足于在实现中直接使用ActiveRecord,那么您在测试中也可能满足于这样做?

d1_status = ActiveRecord::Base.connection.execute("SELECT status from history where id = #{device1.id} limit 1;").values[0][0]
expect(d1_status).to eq("Offline")

不过,我在这里注意到一些令人不安的推论.您正在编辑历史记录表,但期望得到的结果可能是设备模型.然后,状态方法的实现也与您的问题相关.如果选择此方法,您可能希望为Device#status方法编写其他测试.

猜你在找的Ruby相关文章