Commit 386b9ace authored by Fabio Pitino's avatar Fabio Pitino Committed by Douglas Barbosa Alexandre

Create shared examples and helpers to test EventStore

Have a consistent way of testing publishing and consumption
of events.
parent 53920cb3
...@@ -290,3 +290,43 @@ executed synchronously every time the given event is published. ...@@ -290,3 +290,43 @@ executed synchronously every time the given event is published.
For complex conditions it's best to subscribe to all the events and then handle the logic For complex conditions it's best to subscribe to all the events and then handle the logic
in the `handle_event` method of the subscriber worker. in the `handle_event` method of the subscriber worker.
## Testing
A publisher doesn't must care what subscribed to the event being published. The publisher's
responsibility is to ensure that the event is published correctly.
To test that an event has been published correctly, we can use the RSpec matcher `:publish_event`:
```ruby
it 'publishes a ProjectDeleted event with project id and namespace id' do
expected_data = { project_id: project.id, namespace_id: project.namespace_id }
# The matcher verifies that when the block is called, the block publishes the expected event and data.
expect { destroy_project(project, user, {}) }
.to publish_event(Projects::ProjectDeletedEvent)
.with(expected_data)
end
```
The subscriber must ensure that a published event can be consumed correctly. For this purpose
we have added helpers and shared examples to standardize the way we test subscribers:
```ruby
RSpec.describe MergeRequests::UpdateHeadPipelineWorker do
let(:event) { Ci::PipelineCreatedEvent.new(data: ({ pipeline_id: pipeline.id })) }
# This shared example ensures that an event is published and correctly processed by
# the current subscriber (`described_class`).
it_behaves_like 'consumes the published event' do
let(:event) { event }
end
it 'does something' do
# This helper directly executes `perform` ensuring that `handle_event` is called correctly.
consume_event(subscriber: described_class, event: event)
# run expectations
end
end
```
...@@ -11,17 +11,15 @@ RSpec.describe Geo::CreateRepositoryUpdatedEventWorker do ...@@ -11,17 +11,15 @@ RSpec.describe Geo::CreateRepositoryUpdatedEventWorker do
let(:event) { Repositories::KeepAroundRefsCreatedEvent.new(data: { project_id: project.id }) } let(:event) { Repositories::KeepAroundRefsCreatedEvent.new(data: { project_id: project.id }) }
subject { consume_event(event) } subject { consume_event(subscriber: described_class, event: event) }
def consume_event(event)
described_class.new.perform(event.class.name, event.data)
end
context 'on a Geo primary site' do context 'on a Geo primary site' do
before do before do
stub_current_geo_node(primary_site) stub_current_geo_node(primary_site)
end end
it_behaves_like 'subscribes to event'
include_examples 'an idempotent worker' do include_examples 'an idempotent worker' do
let(:job_args) { [event.class.name, event.data] } let(:job_args) { [event.class.name, event.data] }
......
...@@ -4,16 +4,18 @@ require 'spec_helper' ...@@ -4,16 +4,18 @@ require 'spec_helper'
RSpec.describe Security::Findings::DeleteByJobIdWorker do RSpec.describe Security::Findings::DeleteByJobIdWorker do
let(:job_ids) { [1, 2, 3] } let(:job_ids) { [1, 2, 3] }
let(:event) { Ci::PipelineCreatedEvent.new(data: { job_ids: job_ids }) } let(:event) { Ci::JobArtifactsDeletedEvent.new(data: { job_ids: job_ids }) }
subject(:consume_event) { described_class.new.perform(event.class.name, event.data) } subject { consume_event(subscriber: described_class, event: event) }
before do before do
allow(::Security::Findings::CleanupService).to receive(:delete_by_build_ids) allow(::Security::Findings::CleanupService).to receive(:delete_by_build_ids)
end end
it_behaves_like 'subscribes to event'
it 'initiates the cleanup by build ids' do it 'initiates the cleanup by build ids' do
consume_event subject
expect(::Security::Findings::CleanupService).to have_received(:delete_by_build_ids).with(job_ids) expect(::Security::Findings::CleanupService).to have_received(:delete_by_build_ids).with(job_ids)
end end
......
# frozen_string_literal: true
RSpec.shared_examples 'subscribes to event' do
include AfterNextHelpers
it 'consumes the published event', :sidekiq_inline do
expect_next(described_class)
.to receive(:handle_event)
.with(instance_of(event.class))
.and_call_original
::Gitlab::EventStore.publish(event)
end
end
def consume_event(subscriber:, event:)
subscriber.new.perform(event.class.name, event.data)
end
...@@ -11,11 +11,9 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker do ...@@ -11,11 +11,9 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker do
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref) } let(:pipeline) { create(:ci_pipeline, project: project, ref: ref) }
let(:event) { Ci::PipelineCreatedEvent.new(data: { pipeline_id: pipeline.id }) } let(:event) { Ci::PipelineCreatedEvent.new(data: { pipeline_id: pipeline.id }) }
subject { consume_event(event) } subject { consume_event(subscriber: described_class, event: event) }
def consume_event(event) it_behaves_like 'subscribes to event'
described_class.new.perform(event.class.name, event.data)
end
context 'when merge requests already exist for this source branch', :sidekiq_inline do context 'when merge requests already exist for this source branch', :sidekiq_inline do
let(:merge_request_1) do let(:merge_request_1) do
......
...@@ -9,11 +9,9 @@ RSpec.describe Namespaces::UpdateRootStatisticsWorker do ...@@ -9,11 +9,9 @@ RSpec.describe Namespaces::UpdateRootStatisticsWorker do
Projects::ProjectDeletedEvent.new(data: { project_id: 1, namespace_id: namespace_id }) Projects::ProjectDeletedEvent.new(data: { project_id: 1, namespace_id: namespace_id })
end end
subject { consume_event(event) } subject { consume_event(subscriber: described_class, event: event) }
def consume_event(event) it_behaves_like 'subscribes to event'
described_class.new.perform(event.class.name, event.data)
end
it 'enqueues ScheduleAggregationWorker' do it 'enqueues ScheduleAggregationWorker' do
expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(namespace_id) expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(namespace_id)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment