我正在进行Rspec测试,以检查是否使用某些参数调用了ActiveSupport::Notification.instrument
。
问题是,为了使此测试成为FactoryBot
的构建对象的必要条件,但是当我尝试监视ActiveSupport::Notification.instrument
时,总是会收到错误消息:
ActiveSupport::Notifications received :instrument with unexpected arguments
expected: (:asd)
got: ("factory_bot.run_factory", {:factory=>#<FactoryBot::Factory:0x005569b6d30, @al... nil, dispatch: nil, distribution_state: 2, main_category_id: nil>}, :strategy=>:build, :traits=>[]})
似乎FactoryBot会调用activesupport,所以当出于测试目的而对其进行模拟时,我最终会对其进行过度模拟...
代码示例:
班级:
class SomeObject
def initialize(something)
#some code
end
def my_method
ActiveSupport::Notifications.instrument :asd
end
end
规格:
describe "#my_method" do
let(:some_object) { build :some_object }
before do
allow(ActiveSupport::Notifications).to receive(:instrument).with :asd
end
it "calls notifier" do
described_class.new(some_object).my_method
expect(ActiveSupport::Notifications).to have_received(:instrument).with :asd
end
end
我该如何模拟电话而不是FactoryBot的电话。
我只能在嘲笑allow
的那个之前加上另外一个:asd
:
allow(ActiveSupport::Notifications).to receive(:instrument).and_call_original
还有另一种(更好)的方式吗?
答案 0 :(得分:1)
我一般都会避免嘲笑。
我有一个类似的问题,这是我的解决方法:
describe "#my_method" do
let(:some_object) { build :some_object }
before { record_events }
it "calls notifier" do
described_class.new(some_object).my_method
# Make sure your event was triggered
expect(events.map(&:name)).to include('asd')
# Check number of events
expect(events).to be_one
# Check contents of event payload
expect(events.first.payload).to eq({ 'extra' => 'context' })
# Even check the duration of an event
expect(events.first.duration).to be < 3
end
private
attr_reader :events
def record_events
@events = []
ActiveSupport::Notifications.subscribe(:asd) do |*args| #
@events << ActiveSupport::Notifications::Event.new(*args)
end
end
end
ActiveSupport::Notifications
ActiveSupport::Notifications::Event
包装器为您提供了#duration
这样的附加功能ActiveSupport::Notifications.subscribe(/asd/)
对事件名称进行部分匹配@events
数组@events
上的teardown
,则测试之间可能存在依赖性