require 'spec_helper' describe 'AMQP Integration', :bunny, type: :integration do let!(:broker) { MessageDriver::Broker.configure BrokerConfig.config } context "when a queue can't be found" do let(:queue_name) { 'my.lost.queue' } it 'raises a MessageDriver::QueueNotFound error' do expect { broker.dynamic_destination(queue_name, passive: true) }.to raise_error(MessageDriver::QueueNotFound) do |err| expect(err.queue_name).to eq(queue_name) expect(err.nested).to be_a Bunny::NotFound end end end context 'when a channel level exception occurs' do it 'raises a MessageDriver::WrappedError error' do expect { broker.dynamic_destination('not.a.queue', passive: true) }.to raise_error(MessageDriver::WrappedError) { |err| err.nested.should be_a Bunny::ChannelLevelException } end it 'reestablishes the channel transparently' do expect { broker.dynamic_destination('not.a.queue', passive: true) }.to raise_error(MessageDriver::WrappedError) expect { broker.dynamic_destination('', exclusive: true) }.to_not raise_error end context 'when in a transaction' do it 'sets the channel_context as rollback-only until the transaction is finished' do MessageDriver::Client.with_message_transaction do expect { broker.dynamic_destination('not.a.queue', passive: true) }.to raise_error(MessageDriver::WrappedError) expect { broker.dynamic_destination('', exclusive: true) }.to raise_error(MessageDriver::TransactionRollbackOnly) end expect { broker.dynamic_destination('', exclusive: true) }.to_not raise_error end end end context 'when the broker connection fails', pending: 'these spec are busted' do def disrupt_connection #yes, this is very implementation specific broker.adapter.connection.instance_variable_get(:@transport).close end def create_destination(queue_name) broker.dynamic_destination(queue_name, exclusive: true) end it 'raises a MessageDriver::ConnectionError' do dest = create_destination('test_queue') disrupt_connection expect { dest.publish('Reconnection Test') }.to raise_error(MessageDriver::ConnectionError) do |err| expect(err.nested).to be_a Bunny::NetworkErrorWrapper end end it 'seemlessly reconnects' do dest = create_destination('seemless.reconnect.queue') disrupt_connection expect { dest.publish('Reconnection Test 1') }.to raise_error(MessageDriver::ConnectionError) dest = create_destination('seemless.reconnect.queue') dest.publish('Reconnection Test 2') msg = dest.pop_message expect(msg).to_not be_nil expect(msg.body).to eq('Reconnection Test 2') end context 'when in a transaction' do it 'raises a MessageDriver::ConnectionError' do expect { MessageDriver::Client.with_message_transaction do disrupt_connection broker.dynamic_destination('', exclusive: true) end }.to raise_error(MessageDriver::ConnectionError) end it 'sets the channel_context as rollback-only until the transaction is finished' do MessageDriver::Client.with_message_transaction do disrupt_connection expect { broker.dynamic_destination('', exclusive: true) }.to raise_error(MessageDriver::ConnectionError) expect { broker.dynamic_destination('', exclusive: true) }.to raise_error(MessageDriver::TransactionRollbackOnly) end expect { broker.dynamic_destination('', exclusive: true) }.to_not raise_error end end end context 'when an unhandled expection occurs in a transaction' do let(:destination) { broker.dynamic_destination('', exclusive: true) } it 'rolls back the transaction' do expect { MessageDriver::Client.with_message_transaction do destination.publish('Test Message') raise 'unhandled error' end }.to raise_error 'unhandled error' expect(destination.pop_message).to be_nil end it 'allows the next transaction to continue' do expect { MessageDriver::Client.with_message_transaction do destination.publish('Test Message 1') raise 'unhandled error' end }.to raise_error 'unhandled error' expect(destination.pop_message).to be_nil MessageDriver::Client.with_message_transaction do destination.publish('Test Message 2') end msg = destination.pop_message expect(msg).to_not be_nil expect(msg.body).to eq('Test Message 2') end end end