[英]Testing & Mocking Services with Rspec
I created a Service Object called Transaction which processes an order made, sets up the payments and then sets up a model association. 我创建了一个名为Transaction的服务对象,它处理订单,设置付款,然后建立模型关联。
The class is called Transaction with two methods, initialize
and pay
. 该类称为Transaction,有两种方法,
initialize
和pay
。 I am testing it in spec/services/
(it is in app/services
). 我在
spec/services/
测试它(它在app/services
)。
The initialize
method takes in an account
and some parameters passed in by the user to process the order. initialize
方法接受一个account
和一些用户传入的参数来处理订单。
I am trying to test pay
with rspec. 我正试图用rspec测试
pay
。 How do I actually do such a test? 我该如何进行这样的测试? This function has a lot going on.
这个功能有很多功能。 For example, it creates new models, and then sets up some associations between them.
例如,它创建新模型,然后在它们之间建立一些关联。
So far, I created a double account
as follows: 到目前为止,我创建了一个双重
account
,如下所示:
@account = double("account", :confirmed => true, :confirmed? => true)
However, there are many functions (and associations) used in the Transaction pay method. 但是,交易支付方法中使用了许多功能(和关联)。 So for example when these associations are called (once I call
Transaction.pay
in the test), it returns an error: 例如,当调用这些关联时(一旦我在测试中调用
Transaction.pay
),它就会返回一个错误:
ActiveRecord::AssociationTypeMismatch:
Business(#70250016824700) expected, got RSpec::Mocks:.
The business
model is a double just like account
, and added as an attribute to @account
. business
模型是一个双倍的account
,并作为属性添加到@account
。 How can I test my Transaction.pay when it creates new models and associations in there? 如何在其中创建新模型和关联时测试我的Transaction.pay?
Do I need to mock all of them as shown above? 如上所示,我是否需要模拟所有这些? Or is there a better way to do it?
或者有更好的方法吗?
I am using FactoryGirl, but I am unable to use it as my account
model uses Devise. 我正在使用FactoryGirl,但我无法使用它,因为我的
account
模型使用Devise。 Devise test helpers cannot be used outside of controllers, and since I'm testing in services, it won't work. 设计测试助手不能在控制器之外使用,因为我在服务中测试,它将无法工作。
It's hard to be specific, since you've not provided your Transaction class code, but at a high level, here's what I'd recommend: 很难具体,因为你没有提供你的Transaction类代码,但是在高级别,这是我推荐的:
account
. account
做的。 Business
), and if you're creating instances of those from the classes, then they're doubles too. Business
),如果您正在创建类的实例,那么它们也是双倍的。 Here's a vague example with no real implementation: 这是一个模糊的例子,没有真正的实现:
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
You'll note I've only required the transaction file - this helps you be aware of what other classes it depends on, because you'll (ideally) stub the constants, or if necessary, require other files. 你会注意到我只需要事务文件 - 这有助于你了解它依赖的其他类,因为你(理想情况下)存根常量,或者如果需要,需要其他文件。 It'll keep this spec's running time much better too.
它也会使这个规格的运行时间更好。
Also, I only stubbed confirmed?
还有,我只是
confirmed?
, not confirmed
on the account double. ,未在账户上
confirmed
双倍。 From a Rails perspective they mean the same thing, but it's better to use one of them consistently, instead of both. 从Rails的角度来看,它们的意思相同,但最好始终如一地使用其中一个,而不是两者。
If you have a ton of setup (a lot of constants and test doubles), then I'd take that as a sign that this Transaction class probably needs to be broken up into several more specific classes. 如果你有大量的设置(很多常量和测试双打),那么我会把它作为这个Transaction类可能需要分解成几个更具体的类的标志。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.