在单元测试中验证是否正在使用ActiveRecord事务的好方法是什么?

时间:2009-12-14 19:13:29

标签: ruby-on-rails unit-testing activerecord transactions

我有一个执行多个数据库操作的类,我想编写一个单元测试,用于验证这些操作是否都在事务中执行。有什么好干净的方法呢?

以下是一些示例代码,说明了我正在测试的类:

class StructureUpdater
  def initialize(structure)
    @structure = structure
  end

  def update_structure
    SeAccount.transaction do
      delete_existing_statistics
      delete_existing_structure
      add_campaigns
      # ... etc
    end
  end

  private

  def delete_existing_statistics
    # ...
  end

  def delete_existing_structure
    # ...
  end

  def add_campaigns
    # ...
  end
end

1 个答案:

答案 0 :(得分:0)

Rspec允许您声明数据在特定块的范围内已更改。

it "should delete existing statistics" do
    lambda do
        @structure_updater.update_structure
    end.should change(SeAccount, :count).by(3)
end

...或某些此类取决于您的架构的外观等。不确定delete_existing_statistics究竟发生了什么,因此请相应地修改更改子句。

编辑:一开始我不明白这个问题,道歉。您可以尝试断言以确保以给定顺序发生这些调用(同样,使用RSpec):

编辑:您无法在对该事务中 内的呼叫期望的测试中声明对某事务的期望。我能从袖口拿出最接近的是:

describe StructureUpdater do
    before(:each) do
        @structure_updater = StructureUpdater.new(Structure.new)
    end

    it "should update the model within a Transaction" do
        SeAccount.should_receive(:transaction)
        @structure_updater.update_structure
    end

    it "should do these other things" do
        @structure_updater.should_receive(:delete_existing_statistics).ordered
        @structure_updater.should_receive(:delete_existing_structure).ordered
        @structure_updater.should_receive(:add_campaigns).ordered
        @structure_updater.update_structure
    end
end

一个更多尝试:另一个小问题是强制事务块中的一个后续方法调用引发,并断言数据库中没有任何变化。例如,假设Statistic是一个模型,而delete_existing_statistics将更改DB中统计信息的计数,您可以知道如果事务中稍后抛出的异常回滚了该更改,则会在事务中发生调用。类似的东西:

it "should happen in a transaction" do 
    @structure_updater.stub!(:add_campaigns).and_raise
    lambda {@structure_updater.update_structure}.should_not change(Statistic, :count) 
end