7

我创建了一个名为 Transaction 的服务对象,它处理订单,设置付款,然后设置模型关联。

该类称为 Transaction 具有两个方法,initializepay. 我正在测试它spec/services/(它在app/services)。

initialize方法接受account用户传入的一个和一些参数来处理订单。

我正在尝试pay使用 rspec 进行测试。我该如何做这样的测试?这个功能有很多事情要做。例如,它创建新模型,然后在它们之间建立一些关联。

到目前为止,我创建了一个 double account如下:

@account = double("account", :confirmed => true, :confirmed? => true)

但是,交易支付方法中使用了许多功能(和关联)。因此,例如,当调用这些关联时(一旦我Transaction.pay在测试中调用),它会返回一个错误:

ActiveRecord::AssociationTypeMismatch:
Business(#70250016824700) expected, got RSpec::Mocks:.

business模型就像 一样是双重的account,并作为属性添加到@account. 当 Transaction.pay 在其中创建新模型和关联时,如何测试它?

如上所示,我是否需要模拟所有这些?或者有更好的方法吗?

我正在使用 FactoryGirl,但我无法使用它,因为我的account模型使用的是 Devise。设计测试助手不能在控制器之外使用,因为我在服务中进行测试,所以它不起作用。

4

1 回答 1

8

很难具体说明,因为您没有提供 Transaction 类代码,但在高层次上,我建议您这样做:

  • 不要使用 FactoryGirl 或 Devise 助手 - 理想情况下,您正在为此类编写单元测试,因此您不需要任何外部依赖项。
  • 将您正在处理的任何模型实例存根 - 这就是您所做的account
  • 将服务中使用的任何外部类(例如Business)存根,如果您要从这些类中创建这些类的实例,那么它们也是双打的。

这是一个没有实际实现的模糊示例:

require './app/services/transaction'

describe Transaction do
  let(:transaction) { Transaction.new account, :foo => 'bar' }
  let(:account)     { double 'Account', :confirmed? => true }
  let(:business)    { double 'Business', :save => true }

  before :each do
    stub_const 'Business', double(:new => business)
  end

  describe '#pay' do
    it "does stuff" do
      # ...

      transaction.pay

      # ...
    end
  end
end

您会注意到我只需要事务文件 - 这有助于您了解它依赖的其他类,因为您将(理想情况下)存根常量,或者在必要时需要其他文件。它也会使这个规范的运行时间更好。

另外,我只 stubbed confirmed?,而不是confirmed双重帐户。从 Rails 的角度来看,它们的含义相同,但最好始终使用其中之一,而不是同时使用两者。

如果您有大量设置(大量常量和测试替身),那么我认为这表明该 Transaction 类可能需要分解为几个更具体的类。

于 2013-07-01T16:31:24.390 回答