Skip to content

Commit eb8e214

Browse files
committed
Stabilize concurrent binding creation test
The test for concurrent service credential binding creation used threads, which caused sporadic failures in other tests due to database connection interference. This commit rewrites the test to use a spy instead of threads. The spy simulates the race condition by creating a conflicting binding after the database lock is acquired, verifying the code's locking mechanism without the side effects of multi-threading.
1 parent 8e92607 commit eb8e214

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

spec/unit/actions/service_credential_binding_app_create_spec.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,19 @@ module V3
234234
# TODO: Once the unique constraints to allow multiple bindings are removed, this needs to be set to 1
235235
# before { TestConfig.override(max_service_credential_bindings_per_app_service_instance: 1) }
236236

237-
def attempt_precursor
238-
action.precursor(service_instance, app:, message:)
239-
:ok
240-
rescue StandardError => e
241-
e
242-
end
243-
244237
it 'allows only one binding when two creates run in parallel' do
245-
results = [Thread.new { attempt_precursor }, Thread.new { attempt_precursor }].map(&:value)
238+
# This test simulates a race condition for concurrent binding creation using a spy on `service_instance`.
239+
# We mock that a second binding is created after the first one acquires a lock and expect an `UnprocessableCreate` error.
240+
allow(service_instance).to receive(:lock!).and_wrap_original do |m, *args, &block|
241+
m.call(*args, &block)
242+
ServiceBinding.make(service_instance:, app:)
243+
end
244+
245+
expect do
246+
action.precursor(service_instance, app:, message:)
247+
end.to raise_error(ServiceCredentialBindingAppCreate::UnprocessableCreate, 'The app is already bound to the service instance')
246248

247-
expect(ServiceBinding.where(app:, service_instance:).count).to eq(1)
248-
expect(results.count(:ok)).to eq(1)
249-
expect(results.count { |r| r.is_a?(VCAP::CloudController::V3::ServiceBindingCreate::UnprocessableCreate) }).to eq(1)
250-
expect(results.grep(Exception).map(&:message)).to include('The app is already bound to the service instance')
249+
expect(service_instance).to have_received(:lock!)
251250
end
252251
end
253252

0 commit comments

Comments
 (0)