Commit 207688e5 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'fix_next_instance_of_rspec_mock_helper' into 'master'

Fix the `_next_instance_of` mock helpers

See merge request gitlab-org/gitlab!40763
parents b4a3ed33 acdc0b87
...@@ -106,7 +106,7 @@ end ...@@ -106,7 +106,7 @@ end
Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported. Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported.
``` ```
### Alternative: `expect_next_instance_of` or `allow_next_instance_of` ### Alternative: `expect_next_instance_of`, `allow_next_instance_of`, `expect_next_found_instance_of` or `allow_next_found_instance_of`
Instead of writing: Instead of writing:
...@@ -130,8 +130,21 @@ end ...@@ -130,8 +130,21 @@ end
allow_next_instance_of(Project) do |project| allow_next_instance_of(Project) do |project|
allow(project).to receive(:add_import_job) allow(project).to receive(:add_import_job)
end end
# Do this:
expect_next_found_instance_of(Project) do |project|
expect(project).to receive(:add_import_job)
end
# Do this:
allow_next_found_instance_of(Project) do |project|
allow(project).to receive(:add_import_job)
end
``` ```
_**Note:** Since Active Record is not calling the `.new` method on model classes to instantiate the objects,
you should use `expect_next_found_instance_of` or `allow_next_found_instance_of` mock helpers to setup mock on objects returned by Active Record query & finder methods._
If we also want to initialize the instance with some particular arguments, we If we also want to initialize the instance with some particular arguments, we
could also pass it like: could also pass it like:
......
...@@ -115,6 +115,7 @@ RSpec.configure do |config| ...@@ -115,6 +115,7 @@ RSpec.configure do |config|
config.include StubExperiments config.include StubExperiments
config.include StubGitlabCalls config.include StubGitlabCalls
config.include StubGitlabData config.include StubGitlabData
config.include NextFoundInstanceOf
config.include NextInstanceOf config.include NextInstanceOf
config.include TestEnv config.include TestEnv
config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::ControllerHelpers, type: :controller
......
# frozen_string_literal: true
module NextFoundInstanceOf
ERROR_MESSAGE = 'NextFoundInstanceOf mock helpers can only be used with ActiveRecord targets'
def expect_next_found_instance_of(klass)
check_if_active_record!(klass)
stub_allocate(expect(klass)) do |expectation|
yield(expectation)
end
end
def allow_next_found_instance_of(klass)
check_if_active_record!(klass)
stub_allocate(allow(klass)) do |allowance|
yield(allowance)
end
end
private
def check_if_active_record!(klass)
raise ArgumentError.new(ERROR_MESSAGE) unless klass < ActiveRecord::Base
end
def stub_allocate(target)
target.to receive(:allocate).and_wrap_original do |method|
method.call.tap { |allocation| yield(allocation) }
end
end
end
...@@ -54,13 +54,9 @@ RSpec.describe NewNoteWorker do ...@@ -54,13 +54,9 @@ RSpec.describe NewNoteWorker do
let(:note) { create(:note) } let(:note) { create(:note) }
before do before do
# TODO: `allow_next_instance_of` helper method is not working allow_next_found_instance_of(Note) do |note|
# because ActiveRecord is directly calling `.allocate` on model allow(note).to receive(:skip_notification?).and_return(true)
# classes and bypasses the `.new` method call. end
# Fix the `allow_next_instance_of` helper and change these to mock
# the next instance of `Note` model class.
allow(Note).to receive(:find_by).with(id: note.id).and_return(note)
allow(note).to receive(:skip_notification?).and_return(true)
end end
it 'does not create a new note notification' do it 'does not create a new note notification' do
......
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