我们正在维护多个Rails-Apps,这些应用程序都存在类似的问题,我们没有一个非常好的解决方案:所有这些应用程序都包含需要在其生命周期中对外部服务进行API调用的模型。
可能的情况:
我们对 NOT 的体验是一个很好的解决方案:将这些调用添加到模型的after_*
回调中。由于这会快速打破测试,因此现在所有工厂都必须处理api调用。
我正在寻找一种组织这些API调用的好方法。你们是怎么做到的?
我们提出的想法,我认为这不是真正的理想:
答案 0 :(得分:2)
如果您担心测试,可以put the callback methods into a separate class并在测试期间模拟回调类。以下Foo
和FooCallbacks
类给出了使用RSpec的示例:
class Foo < ActiveRecord::Base
after_save FooCallbacks
end
class FooCallbacks
def self.after_save
fail "Call to external API"
end
end
您可以编写并成功运行如下规范:
describe Foo do
before do
allow(FooCallbacks).to receive(:after_save)
end
it "should not invoke real APIs" do
Foo.create
end
end
答案 1 :(得分:1)
这就是我现在的意思,在建议之后:
在Foo
:
class Foo < ActiveRecord::Base
before_save Foo::DataSync
end
Foo:DataSync
看起来像这样:
class Foo::DataSync
def self.before_save(foo)
...do the API-Calls...
end
end
现在在rspec中进行测试我添加了这个:
至spec_helper.rb
:
config.before(:each) do
Foo::DataSync.stub(:before_save)
end
请注意config.before(:suite)
无效,因为当时未加载Foo:DataSync
。
现在foo_spec.rb
只包含这个:
describe Foo do
let(:foo) {create(:foo)}
it "will sync its data before every save" do
expect(Foo::DataSync).to receive(:before_save).with(foo)
foo.save
end
end
Foo::DataSync
可以像这样进行测试:
describe Foo::DataSync do
let!(:foo) {create(:foo)}
before do
Foo::DataSync.unstub(:before_save)
end
after do
Foo::DataSync.stub(:before_save)
end
describe "#before_save" do
...my examples...
end
end