Rspec传递类方法但是实例方法失败

时间:2016-12-29 04:49:36

标签: ruby-on-rails rspec rspec-rails rspec3

我正在尝试编写失败的Rspec测试。实际测试与更长的代码相关联,但我将问题缩小到它正在测试的类方法。

以下是Rspec中的测试:

context "For '.CASH.' as a stock" do
  let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') }

  describe "When update_stock runs on it" do
    it "should still have an 'Available' status" do
      # status should be 'Error' and test should fail
      Stock.change_to_error
      expect(cash.status).to eq('Available')
    end
  end
end

这是在Stock.rb中测试模型类方法:

def self.change_to_error
  self.all.each do |stock|
    stock.status = "Error"
    stock.save
  end
end

出于某种原因,这传递了。但是,如果我将其更改为使用实例方法,它将会失败:

如果stock_spec.rb更改为实例方法:

context "For '.CASH.' as a stock" do
let!(:cash) { FactoryGirl.create(:stock, symbol: '.CASH.', name: 'cash', status: 'Available') }

  describe "When update_stock runs on it" do
    it "should still have an 'Available' status" do
        # status should be 'Error' and test should fail
        cash.change_to_error
        expect(cash.status).to eq('Available')
    end
  end
end

如果stock.rb类方法变成了实例方法:

def change_to_error
  self.status = 'Error'
  self.save
end

这会过去。不幸的是,我必须使用类方法而不是实例方法,因为我想更新数据库中的所有股票。 “Change_to_error”方法就是解决问题的方法。有没有人知道它为什么会失败时作为类方法传递?但是当它使用实例方法时它会正确失败吗?

实际上,正在发生的是类方法不会更改'cash'的status属性,但实例方法会更改。我不知道为什么会这样。

仅供参考,我正在使用rspec-rails

1 个答案:

答案 0 :(得分:1)

解决方案:需要在'Stock.change_to_error'之后和期望行之前加上'cash.reload'。

使用mvn archetype:create时,在测试之前创建对象。更新对象外部的基础数据会导致实例过时。在其上调用let!会强制ActiveRecord从数据库中刷新它。

当您使用reload时,RSpec不会在您第一次引用属性时调用该块,在本例中为let。因此,在您的第一个示例中,您根本没有记录cash,然后检查change_to_error上的状态,这是在cash行上创建的记录。在第二个示例中,创建了expect对象,然后更改为错误。我建议拖尾你的日志来确认这个(cash

如果更改为tail -f log/test.log,RSpec将在每个示例运行之前创建对象。另一种方法是在您的示例中引用let!,然后在创建的所有记录上调用cash