Commit 996dfd52 authored by Robert May's avatar Robert May

Merge branch 'next_found_instances_of' into 'master'

Add call number to `(allow|expect)_next_found_instances_of` helper

See merge request gitlab-org/gitlab!80721
parents abe2354e 9570e380
......@@ -166,6 +166,18 @@ end
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._
It is also possible to set mocks and expectations for multiple instances of the same Active Record model by using the `expect_next_found_(number)_instances_of` and `allow_next_found_(number)_instances_of` helpers, like so;
```ruby
expect_next_found_2_instances_of(Project) do |project|
expect(project).to receive(:add_import_job)
end
allow_next_found_2_instances_of(Project) do |project|
allow(project).to receive(:add_import_job)
end
```
If we also want to initialize the instance with some particular arguments, we
could also pass it like:
......
......@@ -2,19 +2,36 @@
module NextFoundInstanceOf
ERROR_MESSAGE = 'NextFoundInstanceOf mock helpers can only be used with ActiveRecord targets'
HELPER_METHOD_PATTERN = /(?:allow|expect)_next_found_(?<number>\d+)_instances_of/.freeze
def expect_next_found_instance_of(klass)
def method_missing(method_name, ...)
return super unless match_data = method_name.match(HELPER_METHOD_PATTERN)
helper_method = method_name.to_s.sub("_#{match_data[:number]}", '')
public_send(helper_method, *args, match_data[:number].to_i, &block)
end
def expect_next_found_instance_of(klass, &block)
expect_next_found_instances_of(klass, nil, &block)
end
def expect_next_found_instances_of(klass, number)
check_if_active_record!(klass)
stub_allocate(expect(klass), klass) do |expectation|
stub_allocate(expect(klass), klass, number) do |expectation|
yield(expectation)
end
end
def allow_next_found_instance_of(klass)
def allow_next_found_instance_of(klass, &block)
allow_next_found_instances_of(klass, nil, &block)
end
def allow_next_found_instances_of(klass, number)
check_if_active_record!(klass)
stub_allocate(allow(klass), klass) do |allowance|
stub_allocate(allow(klass), klass, number) do |allowance|
yield(allowance)
end
end
......@@ -25,8 +42,11 @@ module NextFoundInstanceOf
raise ArgumentError, ERROR_MESSAGE unless klass < ActiveRecord::Base
end
def stub_allocate(target, klass)
target.to receive(:allocate).and_wrap_original do |method|
def stub_allocate(target, klass, number)
stub = receive(:allocate)
stub.exactly(number).times if number
target.to stub.and_wrap_original do |method|
method.call.tap do |allocation|
# ActiveRecord::Core.allocate returns a frozen object:
# https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activerecord/lib/active_record/core.rb#L620
......
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