使用Rspec进行测试和模拟服务

dar*_*sky 6 ruby testing rspec ruby-on-rails

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

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

initialize方法接受account用户传入的一些参数以处理订单.

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

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

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

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

ActiveRecord::AssociationTypeMismatch:
Business(#70250016824700) expected, got RSpec::Mocks:.
Run Code Online (Sandbox Code Playgroud)

business模型是双倍的account,并作为属性添加@account.如何在其中创建新模型和关联时测试我的Transaction.pay?

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

我正在使用FactoryGirl,但我无法使用它,因为我的account模型使用Devise.设计测试助手不能在控制器之外使用,因为我在服务中测试,它将无法工作.

pat*_*pat 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
Run Code Online (Sandbox Code Playgroud)

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

另外,我只是存根confirmed?,而不是confirmed帐户双.从Rails的角度来看,它们的意思相同,但最好始终如一地使用其中一个,而不是两者.

如果你有大量的设置(很多常量和测试双打),那么我会把它作为这个Transaction类可能需要分解成几个更具体的类的标志.