Commit ab3ddae0 authored by Alex Kalderimis's avatar Alex Kalderimis Committed by Alex Kalderimis

Remove allow_any_instance and expect_any_instance

Adds AfterNextHelpers, a more fluent interface to allow_any_instance

This allows `after_next` to support the `to/not_to` API developers
expect.
parent 5bd48e0f
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe PostReceive do RSpec.describe PostReceive do
include AfterNextHelpers
include ServicesHelper
let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
let(:changes_with_master) { "#{changes}\n423423 797823 refs/heads/master" } let(:changes_with_master) { "#{changes}\n423423 797823 refs/heads/master" }
let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") } let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
...@@ -14,26 +17,19 @@ RSpec.describe PostReceive do ...@@ -14,26 +17,19 @@ RSpec.describe PostReceive do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
describe "#process_project_changes" do describe "#process_project_changes" do
before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
end
context 'after project changes hooks' do context 'after project changes hooks' do
let(:fake_hook_data) { Hash.new(event_name: 'repository_update') } let(:fake_hook_data) { Hash.new(event_name: 'repository_update') }
before do before do
allow(RepositoryPushAuditEventWorker).to receive(:perform_async) allow(RepositoryPushAuditEventWorker).to receive(:perform_async)
allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data) allow_next(Gitlab::DataBuilder::Repository)
# silence hooks so we can isolate .to receive(:update).and_return(fake_hook_data)
allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
expect_next_instance_of(Git::TagPushService) do |service| # silence hooks so we can isolate
expect(service).to receive(:execute).and_return(true) allow_next(Key).to receive(:post_create_hook).and_return(true)
end
expect_next_instance_of(Git::BranchPushService) do |service| expect_next(Git::TagPushService).to receive(:execute).and_return(true)
expect(service).to receive(:execute).and_return(true) expect_next(Git::BranchPushService).to receive(:execute).and_return(true)
end
end end
context 'when DB is readonly' do context 'when DB is readonly' do
...@@ -81,9 +77,7 @@ RSpec.describe PostReceive do ...@@ -81,9 +77,7 @@ RSpec.describe PostReceive do
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } allow(Gitlab::Geo).to receive(:primary?) { true }
expect_next_instance_of(::Geo::RepositoryUpdatedService) do |service| expect_execution_of(::Geo::RepositoryUpdatedService)
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
...@@ -103,26 +97,23 @@ RSpec.describe PostReceive do ...@@ -103,26 +97,23 @@ RSpec.describe PostReceive do
let(:gl_repository) { wiki.repository.repo_type.identifier_for_container(wiki) } let(:gl_repository) { wiki.repository.repo_type.identifier_for_container(wiki) }
it 'calls Git::WikiPushService#execute' do it 'calls Git::WikiPushService#execute' do
expect_next_instance_of(::Git::WikiPushService) do |service| expect_next(::Git::WikiPushService).to receive(:execute)
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
context 'assuming calls to process_changes are successful' do context 'assuming calls to process_changes are successful' do
before do before do
allow_next_instance_of(::Git::WikiPushService) do |service| # We instantiate the wiki here so that expect_next(ProjectWiki) captures the right thing.
allow(service).to receive(:execute) project.wiki
end
allow_next(Git::WikiPushService).to receive(:execute)
end end
it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do it 'calls Geo::RepositoryUpdatedService when running on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } allow(Gitlab::Geo).to receive(:primary?) { true }
expect_next_instance_of(::Geo::RepositoryUpdatedService) do |service| expect_execution_of(::Geo::RepositoryUpdatedService)
expect(service).to receive(:execute)
end
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Global search' do RSpec.describe 'Global search' do
include AfterNextHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) } let(:project) { create(:project, namespace: user.namespace) }
...@@ -22,9 +24,7 @@ RSpec.describe 'Global search' do ...@@ -22,9 +24,7 @@ RSpec.describe 'Global search' do
describe 'I search through the issues and I see pagination' do describe 'I search through the issues and I see pagination' do
before do before do
allow_next_instance_of(SearchService) do |instance| allow_next(SearchService).to receive(:per_page).and_return(1)
allow(instance).to receive(:per_page).and_return(1)
end
create_list(:issue, 2, project: project, title: 'initial') create_list(:issue, 2, project: project, title: 'initial')
end end
......
# frozen_string_literal: true
require_relative './next_instance_of'
module AfterNextHelpers
class DeferredExpectation
include ::NextInstanceOf
include ::RSpec::Matchers
include ::RSpec::Mocks::ExampleMethods
def initialize(klass, args, level:)
@klass = klass
@args = args
@level = level.to_sym
end
def to(condition)
run_condition(condition, asserted: true)
end
def not_to(condition)
run_condition(condition, asserted: false)
end
private
attr_reader :klass, :args, :level
def run_condition(condition, asserted:)
msg = asserted ? :to : :not_to
case level
when :expect
expect_next_instance_of(klass, *args) { |instance| expect(instance).send(msg, condition) }
when :allow
allow_next_instance_of(klass, *args) { |instance| allow(instance).send(msg, condition) }
else
raise "Unknown level: #{level}"
end
end
end
def allow_next(klass, *args)
DeferredExpectation.new(klass, args, level: :allow)
end
def expect_next(klass, *args)
DeferredExpectation.new(klass, args, level: :expect)
end
end
# frozen_string_literal: true # frozen_string_literal: true
module NextInstanceOf module NextInstanceOf
def expect_next_instance_of(klass, *new_args) def expect_next_instance_of(klass, *new_args, &blk)
stub_new(expect(klass), *new_args) do |expectation| stub_new(expect(klass), *new_args, &blk)
yield(expectation)
end
end end
def allow_next_instance_of(klass, *new_args) def allow_next_instance_of(klass, *new_args, &blk)
stub_new(allow(klass), *new_args) do |allowance| stub_new(allow(klass), *new_args, &blk)
yield(allowance)
end
end end
private private
def stub_new(target, *new_args) def stub_new(target, *new_args, &blk)
receive_new = receive(:new) receive_new = receive(:new)
receive_new.with(*new_args) if new_args.any? receive_new.with(*new_args) if new_args.any?
target.to receive_new.and_wrap_original do |method, *original_args| target.to receive_new.and_wrap_original do |method, *original_args|
method.call(*original_args).tap do |instance| method.call(*original_args).tap(&blk)
yield(instance)
end
end end
end end
end end
# frozen_string_literal: true
require_relative './after_next_helpers'
module ServicesHelper
include AfterNextHelpers
def expect_execution_of(service_class, *args)
expect_next(service_class, *args).to receive(:execute)
end
end
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe PostReceive do RSpec.describe PostReceive do
include AfterNextHelpers
include ServicesHelper
let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") } let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) } let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
...@@ -18,8 +21,8 @@ RSpec.describe PostReceive do ...@@ -18,8 +21,8 @@ RSpec.describe PostReceive do
described_class.new.perform(gl_repository, key_id, changes) described_class.new.perform(gl_repository, key_id, changes)
end end
context "as a sidekiq worker" do context 'as a sidekiq worker' do
it "responds to #perform" do it 'responds to #perform' do
expect(described_class.new).to respond_to(:perform) expect(described_class.new).to respond_to(:perform)
end end
end end
...@@ -30,7 +33,7 @@ RSpec.describe PostReceive do ...@@ -30,7 +33,7 @@ RSpec.describe PostReceive do
"Triggered hook for non-existing gl_repository \"#{gl_repository}\"" "Triggered hook for non-existing gl_repository \"#{gl_repository}\""
end end
it "returns false and logs an error" do it 'returns false and logs an error' do
expect(Gitlab::GitLogger).to receive(:error).with("POST-RECEIVE: #{error_message}") expect(Gitlab::GitLogger).to receive(:error).with("POST-RECEIVE: #{error_message}")
expect(perform).to be(false) expect(perform).to be(false)
end end
...@@ -42,9 +45,7 @@ RSpec.describe PostReceive do ...@@ -42,9 +45,7 @@ RSpec.describe PostReceive do
it 'does not log an error' do it 'does not log an error' do
expect(Gitlab::GitLogger).not_to receive(:error) expect(Gitlab::GitLogger).not_to receive(:error)
expect(Gitlab::GitPostReceive).to receive(:new).and_call_original expect(Gitlab::GitPostReceive).to receive(:new).and_call_original
expect_any_instance_of(described_class) do |instance| expect_next(described_class).to receive(:process_snippet_changes)
expect(instance).to receive(:process_snippet_changes)
end
perform perform
end end
...@@ -61,13 +62,13 @@ RSpec.describe PostReceive do ...@@ -61,13 +62,13 @@ RSpec.describe PostReceive do
end end
end end
describe "#process_project_changes" do describe '#process_project_changes' do
context 'with an empty project' do context 'with an empty project' do
let(:empty_project) { create(:project, :empty_repo) } let(:empty_project) { create(:project, :empty_repo) }
let(:changes) { "123456 789012 refs/heads/tést1\n" } let(:changes) { "123456 789012 refs/heads/tést1\n" }
before do before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(empty_project.owner) allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(empty_project.owner)
# Need to mock here so we can expect calls on project # Need to mock here so we can expect calls on project
allow(Gitlab::GlRepository).to receive(:parse).and_return([empty_project, empty_project, Gitlab::GlRepository::PROJECT]) allow(Gitlab::GlRepository).to receive(:parse).and_return([empty_project, empty_project, Gitlab::GlRepository::PROJECT])
end end
...@@ -97,9 +98,9 @@ RSpec.describe PostReceive do ...@@ -97,9 +98,9 @@ RSpec.describe PostReceive do
end end
context 'empty changes' do context 'empty changes' do
it "does not call any PushService but runs after project hooks" do it 'does not call any PushService but runs after project hooks' do
expect(Git::ProcessRefChangesService).not_to receive(:new) expect(Git::ProcessRefChangesService).not_to receive(:new)
expect_next_instance_of(SystemHooksService) { |service| expect(service).to receive(:execute_hooks) } expect_next(SystemHooksService).to receive(:execute_hooks)
perform(changes: "") perform(changes: "")
end end
...@@ -121,7 +122,7 @@ RSpec.describe PostReceive do ...@@ -121,7 +122,7 @@ RSpec.describe PostReceive do
let(:push_service) { double(execute: true) } let(:push_service) { double(execute: true) }
before do before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner) allow_next(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
allow(Gitlab::GlRepository).to receive(:parse).and_return([project, project, Gitlab::GlRepository::PROJECT]) allow(Gitlab::GlRepository).to receive(:parse).and_return([project, project, Gitlab::GlRepository::PROJECT])
end end
...@@ -135,7 +136,7 @@ RSpec.describe PostReceive do ...@@ -135,7 +136,7 @@ RSpec.describe PostReceive do
end end
end end
context "branches" do context 'branches' do
let(:changes) do let(:changes) do
<<~EOF <<~EOF
123456 789012 refs/heads/tést1 123456 789012 refs/heads/tést1
...@@ -157,9 +158,7 @@ RSpec.describe PostReceive do ...@@ -157,9 +158,7 @@ RSpec.describe PostReceive do
end end
it 'calls Git::ProcessRefChangesService' do it 'calls Git::ProcessRefChangesService' do
expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect_next(Git::ProcessRefChangesService).to receive(:execute).and_return(true)
expect(service).to receive(:execute).and_return(true)
end
perform perform
end end
...@@ -191,7 +190,7 @@ RSpec.describe PostReceive do ...@@ -191,7 +190,7 @@ RSpec.describe PostReceive do
end end
end end
context "tags" do context 'tags' do
let(:changes) do let(:changes) do
<<~EOF <<~EOF
654321 210987 refs/tags/tag1 654321 210987 refs/tags/tag1
...@@ -219,9 +218,7 @@ RSpec.describe PostReceive do ...@@ -219,9 +218,7 @@ RSpec.describe PostReceive do
end end
it 'calls Git::ProcessRefChangesService' do it 'calls Git::ProcessRefChangesService' do
expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect_execution_of(Git::ProcessRefChangesService)
expect(service).to receive(:execute).and_return(true)
end
perform perform
end end
...@@ -236,7 +233,7 @@ RSpec.describe PostReceive do ...@@ -236,7 +233,7 @@ RSpec.describe PostReceive do
it_behaves_like 'updating remote mirrors' it_behaves_like 'updating remote mirrors'
end end
context "merge-requests" do context 'merge-requests' do
let(:changes) { "123456 789012 refs/merge-requests/123" } let(:changes) { "123456 789012 refs/merge-requests/123" }
it "does not call any of the services" do it "does not call any of the services" do
...@@ -250,19 +247,19 @@ RSpec.describe PostReceive do ...@@ -250,19 +247,19 @@ RSpec.describe PostReceive do
context 'after project changes hooks' do context 'after project changes hooks' do
let(:changes) { '123456 789012 refs/heads/tést' } let(:changes) { '123456 789012 refs/heads/tést' }
let(:fake_hook_data) { Hash.new(event_name: 'repository_update') } let(:fake_hook_data) { { event_name: 'repository_update' } }
before do before do
allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data) allow(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
# silence hooks so we can isolate # silence hooks so we can isolate
allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true) allow_next(Key).to receive(:post_create_hook).and_return(true)
expect_next_instance_of(Git::ProcessRefChangesService) do |service| expect_execution_of(Git::ProcessRefChangesService)
expect(service).to receive(:execute).and_return(true)
end
end end
it 'calls SystemHooksService' do it 'calls SystemHooksService' do
expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true) expect_next(SystemHooksService)
.to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks)
.and_return(true)
perform perform
end end
...@@ -299,7 +296,7 @@ RSpec.describe PostReceive do ...@@ -299,7 +296,7 @@ RSpec.describe PostReceive do
end end
end end
context "master" do context 'master' do
let(:default_branch) { 'master' } let(:default_branch) { 'master' }
let(:oldrev) { '012345' } let(:oldrev) { '012345' }
let(:newrev) { '6789ab' } let(:newrev) { '6789ab' }
...@@ -313,18 +310,13 @@ RSpec.describe PostReceive do ...@@ -313,18 +310,13 @@ RSpec.describe PostReceive do
let(:raw_repo) { double('RawRepo') } let(:raw_repo) { double('RawRepo') }
it 'processes the changes on the master branch' do it 'processes the changes on the master branch' do
expect_next_instance_of(Git::WikiPushService) do |service| expect_next(Git::WikiPushService).to receive(:execute)
expect(service).to receive(:execute).and_call_original
end
expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch)
expect(project.wiki.repository).to receive(:raw).and_return(raw_repo)
expect(raw_repo).to receive(:raw_changes_between).once.with(oldrev, newrev).and_return([])
perform perform
end end
end end
context "branches" do context 'branches' do
let(:changes) do let(:changes) do
<<~EOF <<~EOF
123456 789012 refs/heads/tést1 123456 789012 refs/heads/tést1
...@@ -333,9 +325,7 @@ RSpec.describe PostReceive do ...@@ -333,9 +325,7 @@ RSpec.describe PostReceive do
end end
before do before do
allow_next_instance_of(Git::WikiPushService) do |service| allow_next(Git::WikiPushService).to receive(:execute)
allow(service).to receive(:execute)
end
end end
it 'expires the branches cache' do it 'expires the branches cache' do
...@@ -353,24 +343,21 @@ RSpec.describe PostReceive do ...@@ -353,24 +343,21 @@ RSpec.describe PostReceive do
end end
end end
context "webhook" do context 'webhook' do
it "fetches the correct project" do it 'fetches the correct project' do
expect(Project).to receive(:find_by).with(id: project.id) expect(Project).to receive(:find_by).with(id: project.id)
perform perform
end end
it "does not run if the author is not in the project" do it "does not run if the author is not in the project" do
allow_any_instance_of(Gitlab::GitPostReceive) allow_next(Gitlab::GitPostReceive).to receive(:identify_using_ssh_key).and_return(nil)
.to receive(:identify_using_ssh_key)
.and_return(nil)
expect(project).not_to receive(:execute_hooks) expect(project).not_to receive(:execute_hooks)
expect(perform).to be_falsey expect(perform).to be_falsey
end end
it "asks the project to trigger all hooks" do it 'asks the project to trigger all hooks' do
create(:project_hook, push_events: true, tag_push_events: true, project: project) create(:project_hook, push_events: true, tag_push_events: true, project: project)
create(:custom_issue_tracker_service, push_events: true, merge_requests_events: false, project: project) create(:custom_issue_tracker_service, push_events: true, merge_requests_events: false, project: project)
allow(Project).to receive(:find_by).and_return(project) allow(Project).to receive(:find_by).and_return(project)
...@@ -381,11 +368,9 @@ RSpec.describe PostReceive do ...@@ -381,11 +368,9 @@ RSpec.describe PostReceive do
perform perform
end end
it "enqueues a UpdateMergeRequestsWorker job" do it 'enqueues a UpdateMergeRequestsWorker job' do
allow(Project).to receive(:find_by).and_return(project) allow(Project).to receive(:find_by).and_return(project)
expect_next_instance_of(MergeRequests::PushedBranchesService) do |service| expect_next(MergeRequests::PushedBranchesService).to receive(:execute).and_return(%w(tést))
expect(service).to receive(:execute).and_return(%w(tést))
end
expect(UpdateMergeRequestsWorker).to receive(:perform_async).with(project.id, project.owner.id, any_args) expect(UpdateMergeRequestsWorker).to receive(:perform_async).with(project.id, project.owner.id, any_args)
......
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