message-driver 0.1.0 → 0.2.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +18 -7
  4. data/CHANGELOG.md +12 -2
  5. data/Gemfile +17 -0
  6. data/Guardfile +8 -4
  7. data/README.md +14 -5
  8. data/Rakefile +44 -11
  9. data/examples/basic_producer_and_consumer/Gemfile +5 -0
  10. data/examples/basic_producer_and_consumer/common.rb +17 -0
  11. data/examples/basic_producer_and_consumer/consumer.rb +24 -0
  12. data/examples/basic_producer_and_consumer/producer.rb +33 -0
  13. data/features/.nav +8 -0
  14. data/features/CHANGELOG.md +12 -2
  15. data/features/amqp_specific_features/binding_amqp_destinations.feature +7 -7
  16. data/features/amqp_specific_features/declaring_amqp_exchanges.feature +3 -3
  17. data/features/amqp_specific_features/nack_redelivered_messages.feature +92 -0
  18. data/features/amqp_specific_features/requeueing_on_nack.feature +44 -0
  19. data/features/amqp_specific_features/server_named_destinations.feature +5 -5
  20. data/features/client_acks.feature +92 -0
  21. data/features/destination_metadata.feature +9 -11
  22. data/features/dynamic_destinations.feature +7 -7
  23. data/features/error_handling.feature +11 -9
  24. data/features/logging.feature +14 -0
  25. data/features/message_consumers/auto_ack_consumers.feature +79 -0
  26. data/features/message_consumers/manual_ack_consumers.feature +95 -0
  27. data/features/message_consumers/transactional_ack_consumers.feature +77 -0
  28. data/features/message_consumers.feature +54 -0
  29. data/features/publishing_a_message.feature +6 -10
  30. data/features/publishing_with_transactions.feature +10 -14
  31. data/features/rabbitmq_specific_features/dead_letter_queueing.feature +116 -0
  32. data/features/step_definitions/dynamic_destinations_steps.rb +3 -3
  33. data/features/step_definitions/error_handling_steps.rb +4 -2
  34. data/features/step_definitions/logging_steps.rb +28 -0
  35. data/features/step_definitions/message_consumers_steps.rb +29 -0
  36. data/features/step_definitions/steps.rb +60 -9
  37. data/features/support/broker_config_helper.rb +19 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/firewall_helper.rb +8 -11
  40. data/features/support/message_table_matcher.rb +21 -5
  41. data/features/support/test_runner.rb +39 -16
  42. data/lib/message_driver/adapters/base.rb +51 -4
  43. data/lib/message_driver/adapters/bunny_adapter.rb +251 -127
  44. data/lib/message_driver/adapters/in_memory_adapter.rb +97 -18
  45. data/lib/message_driver/adapters/stomp_adapter.rb +127 -0
  46. data/lib/message_driver/broker.rb +23 -24
  47. data/lib/message_driver/client.rb +157 -0
  48. data/lib/message_driver/destination.rb +7 -4
  49. data/lib/message_driver/errors.rb +27 -0
  50. data/lib/message_driver/logging.rb +11 -0
  51. data/lib/message_driver/message.rb +8 -0
  52. data/lib/message_driver/subscription.rb +18 -0
  53. data/lib/message_driver/vendor/.document +0 -0
  54. data/lib/message_driver/vendor/nesty/nested_error.rb +26 -0
  55. data/lib/message_driver/vendor/nesty.rb +1 -0
  56. data/lib/message_driver/version.rb +1 -1
  57. data/lib/message_driver.rb +4 -2
  58. data/message-driver.gemspec +4 -4
  59. data/spec/integration/{amqp_integration_spec.rb → bunny/amqp_integration_spec.rb} +29 -28
  60. data/spec/integration/bunny/bunny_adapter_spec.rb +339 -0
  61. data/spec/integration/in_memory/in_memory_adapter_spec.rb +126 -0
  62. data/spec/integration/stomp/stomp_adapter_spec.rb +142 -0
  63. data/spec/spec_helper.rb +5 -2
  64. data/spec/support/shared/adapter_examples.rb +17 -0
  65. data/spec/support/shared/client_ack_examples.rb +18 -0
  66. data/spec/support/shared/context_examples.rb +14 -0
  67. data/spec/support/shared/destination_examples.rb +4 -5
  68. data/spec/support/shared/subscription_examples.rb +146 -0
  69. data/spec/support/shared/transaction_examples.rb +43 -0
  70. data/spec/support/utils.rb +14 -0
  71. data/spec/units/message_driver/adapters/base_spec.rb +38 -19
  72. data/spec/units/message_driver/broker_spec.rb +71 -18
  73. data/spec/units/message_driver/client_spec.rb +375 -0
  74. data/spec/units/message_driver/destination_spec.rb +9 -0
  75. data/spec/units/message_driver/logging_spec.rb +18 -0
  76. data/spec/units/message_driver/message_spec.rb +36 -0
  77. data/spec/units/message_driver/subscription_spec.rb +24 -0
  78. data/test_lib/broker_config.rb +50 -20
  79. metadata +83 -45
  80. data/.rbenv-version +0 -1
  81. data/lib/message_driver/exceptions.rb +0 -18
  82. data/lib/message_driver/message_publisher.rb +0 -15
  83. data/spec/integration/message_driver/adapters/bunny_adapter_spec.rb +0 -301
  84. data/spec/units/message_driver/adapters/in_memory_adapter_spec.rb +0 -43
  85. data/spec/units/message_driver/message_publisher_spec.rb +0 -65
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+
3
+ require 'message_driver/adapters/stomp_adapter'
4
+
5
+ module MessageDriver::Adapters
6
+ describe StompAdapter, :stomp, type: :integration do
7
+
8
+ let(:valid_connection_attrs) { BrokerConfig.config }
9
+
10
+ describe "#initialize" do
11
+ let(:connection_attrs) { valid_connection_attrs }
12
+
13
+ context "differing stomp versions" do
14
+ shared_examples "raises a stomp error" do
15
+ it "raises an error" do
16
+ stub_const("Stomp::Version::STRING", version)
17
+ expect {
18
+ described_class.new(connection_attrs)
19
+ }.to raise_error MessageDriver::Error, "stomp 1.2.10 or a later version of the 1.2.x series is required for the stomp adapter"
20
+ end
21
+ end
22
+ shared_examples "doesn't raise a stomp error" do
23
+ it "doesn't raise an an error" do
24
+ stub_const("Stomp::Version::STRING", version)
25
+ adapter = nil
26
+ expect {
27
+ adapter = described_class.new(connection_attrs)
28
+ }.to_not raise_error
29
+ end
30
+ end
31
+ %w(1.1.0 1.2.9 1.3.0).each do |v|
32
+ context "stomp version #{v}" do
33
+ let(:version) { v }
34
+ include_examples "raises a stomp error"
35
+ end
36
+ end
37
+ %w(1.2.10 1.2.11).each do |v|
38
+ context "stomp version #{v}" do
39
+ let(:version) { v }
40
+ include_examples "doesn't raise a stomp error"
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "the resulting config" do
46
+ let(:connection_attrs) { {hosts: [{host: "my_host"}]} }
47
+ subject(:config) { described_class.new(connection_attrs).config }
48
+
49
+ its([:connect_headers]) { should eq(:"accept-version" => "1.1,1.2") }
50
+ its([:hosts]) { should eq(connection_attrs[:hosts]) }
51
+
52
+ context "when vhost is specified" do
53
+ let(:connection_attrs) { {hosts: [{host: "my_host"}], vhost: "my_vhost"} }
54
+
55
+ it { should_not have_key(:vhost) }
56
+ its([:connect_headers]) { should eq(:"accept-version" => "1.1,1.2", :"host" => "my_vhost") }
57
+ end
58
+
59
+ context "when there are things in the connect_headers" do
60
+ let(:connection_attrs) { {hosts: [{host: "my_host"}], connect_headers: {"foo" => "bar"}} }
61
+
62
+ its([:connect_headers]) { should eq(:"accept-version" => "1.1,1.2", "foo" => "bar") }
63
+
64
+ context "and accept-version is one of the parameters" do
65
+ let(:connection_attrs) { {hosts: [{host: "my_host"}], connect_headers: {"foo" => "bar", :"accept-version" => "foo!"}} }
66
+
67
+ its([:connect_headers]) { should eq(:"accept-version" => "1.1,1.2", "foo" => "bar") }
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ shared_context "a connected stomp adapter" do
74
+ subject(:adapter) { described_class.new(valid_connection_attrs) }
75
+
76
+ before do
77
+ MessageDriver::Broker.configure(adapter: adapter)
78
+ end
79
+
80
+ after do
81
+ adapter.stop
82
+ end
83
+ end
84
+
85
+ it_behaves_like "an adapter" do
86
+ include_context "a connected stomp adapter"
87
+ end
88
+
89
+ describe "#new_context" do
90
+ include_context "a connected stomp adapter"
91
+
92
+ it "returns a StompAdapter::StompContext" do
93
+ expect(adapter.new_context).to be_a StompAdapter::StompContext
94
+ end
95
+ end
96
+
97
+ describe StompAdapter::StompContext do
98
+ include_context "a connected stomp adapter"
99
+ subject(:adapter_context) { adapter.new_context }
100
+
101
+ it_behaves_like "an adapter context"
102
+ it_behaves_like "transactions are not supported"
103
+ it_behaves_like "client acks are not supported"
104
+ it_behaves_like "subscriptions are not supported"
105
+
106
+ describe "#create_destination" do
107
+
108
+ context "the resulting destination" do
109
+ let(:dest_name) { "/queue/stomp_destination_spec" }
110
+ subject(:destination) { adapter_context.create_destination(dest_name) }
111
+
112
+ it { should be_a StompAdapter::Destination }
113
+
114
+ it_behaves_like "a destination"
115
+ include_examples "doesn't support #message_count"
116
+
117
+ describe "pop_message" do
118
+ context "when there is a message on the queue" do
119
+ let(:body) { "Testing stomp pop_message" }
120
+ before do
121
+ destination.publish(body)
122
+ end
123
+
124
+ it "returns the message" do
125
+ msg = destination.pop_message
126
+ expect(msg).to be_a MessageDriver::Adapters::StompAdapter::Message
127
+ expect(msg.body).to eq(body)
128
+ end
129
+ end
130
+
131
+ context "when the queue is empty" do
132
+ it "returns nil" do
133
+ msg = destination.pop_message
134
+ expect(msg).to be_nil
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
data/spec/spec_helper.rb CHANGED
@@ -11,9 +11,12 @@ RSpec.configure do |c|
11
11
 
12
12
  c.reporter.message("Acceptance Tests running with broker config: #{BrokerConfig.config}")
13
13
 
14
- c.filter_run_excluding :no_travis if ENV['TRAVIS']=='true' && ENV['ADAPTER']=='bunny'
14
+ c.filter_run_excluding :no_ci if ENV['CI']=='true' && ENV['ADAPTER'] && ENV['ADAPTER'].start_with?('bunny')
15
15
  if c.inclusion_filter[:all_adapters] == true
16
- c.filter_run BrokerConfig.current_adapter
16
+ BrokerConfig.unconfigured_adapters.each do |a|
17
+ c.filter_run_excluding a
18
+ end
19
+ c.filter_run_including BrokerConfig.current_adapter
17
20
  else
18
21
  c.run_all_when_everything_filtered = true
19
22
  end
@@ -0,0 +1,17 @@
1
+ shared_examples "an adapter" do
2
+ describe "#new_context" do
3
+ it "returns a MessageDriver::Adapters::ContextBase" do
4
+ expect(subject.new_context).to be_a MessageDriver::Adapters::ContextBase
5
+ end
6
+ end
7
+
8
+ describe "#stop" do
9
+ it "invalidates all the adapter contexts" do
10
+ ctx1 = subject.new_context
11
+ ctx2 = subject.new_context
12
+ subject.stop
13
+ expect(ctx1).to_not be_valid
14
+ expect(ctx2).to_not be_valid
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ shared_examples "client acks are supported" do
2
+ describe "#supports_client_acks" do
3
+ it "returns true" do
4
+ expect(subject.supports_client_acks?).to eq(true)
5
+ end
6
+ end
7
+
8
+ it { should respond_to :ack_message }
9
+ it { should respond_to :nack_message }
10
+ end
11
+
12
+ shared_examples "client acks are not supported" do
13
+ describe "#supports_client_acks" do
14
+ it "returns false" do
15
+ expect(subject.supports_client_acks?).to eq(false)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ shared_examples "an adapter context" do
2
+ it { should be_a MessageDriver::Adapters::ContextBase }
3
+
4
+ it "is initially valid" do
5
+ should be_valid
6
+ end
7
+
8
+ describe "#invalidate" do
9
+ it "causes the context to become invalid" do
10
+ subject.invalidate
11
+ expect(subject).to_not be_valid
12
+ end
13
+ end
14
+ end
@@ -9,12 +9,11 @@ shared_examples "a destination" do
9
9
  end
10
10
 
11
11
  context "the result" do
12
- let!(:message) { destination.pop_message }
13
- subject { message }
12
+ subject(:message) { destination.pop_message }
14
13
 
15
14
  it { should be_a MessageDriver::Message::Base }
16
15
  its(:body) { should eq(body) }
17
- its(:headers) { should eq(headers) }
16
+ its(:headers) { should include(headers) }
18
17
  its(:properties) { should_not be_nil }
19
18
  end
20
19
  end
@@ -31,11 +30,11 @@ shared_examples "doesn't support #message_count" do
31
30
  end
32
31
 
33
32
  shared_examples "supports #message_count" do
34
- #FIXME this example fails on travis with the bunny adapter :(
35
- it "reports it's message_count", :no_travis do
33
+ it "reports it's message_count" do
36
34
  expect {
37
35
  destination.publish("msg1")
38
36
  destination.publish("msg2")
37
+ pause_if_needed
39
38
  }.to change{destination.message_count}.by(2)
40
39
  end
41
40
  end
@@ -0,0 +1,146 @@
1
+ shared_examples "subscriptions are not supported" do
2
+ describe "#supports_subscriptions?" do
3
+ it "returns false" do
4
+ expect(subject.supports_subscriptions?).to eq(false)
5
+ end
6
+ end
7
+
8
+ describe "#subscribe" do
9
+ it "raises an error" do
10
+ destination = double("destination")
11
+ consumer = lambda do |m| end
12
+ expect {
13
+ subject.subscribe(destination, &consumer)
14
+ }.to raise_error "#subscribe is not supported by #{subject.adapter.class}"
15
+ end
16
+ end
17
+ end
18
+
19
+ shared_examples "subscriptions are supported" do |subscription_type|
20
+ describe "#supports_subscriptions?" do
21
+ it "returns true" do
22
+ expect(subject.supports_subscriptions?).to eq(true)
23
+ end
24
+ end
25
+
26
+ let(:destination) { adapter_context.create_destination("subscriptions_example_queue") }
27
+
28
+ let(:message1) { "message 1" }
29
+ let(:message2) { "message 2" }
30
+ let(:messages) { [] }
31
+ let(:consumer) do
32
+ lambda do |msg|
33
+ messages << msg
34
+ end
35
+ end
36
+
37
+ describe "#subscribe" do
38
+ before do
39
+ if destination.respond_to? :purge
40
+ destination.purge
41
+ end
42
+ end
43
+
44
+ let(:subscription) { adapter_context.subscribe(destination, &consumer) }
45
+ after do
46
+ subscription.unsubscribe
47
+ end
48
+
49
+ it "returns a MessageDriver::Subscription::Base" do
50
+ expect(subscription).to be_a MessageDriver::Subscription::Base
51
+ end
52
+
53
+ context "the subscription" do
54
+ subject { subscription }
55
+
56
+ it { should be_a MessageDriver::Subscription::Base }
57
+ it { should be_a subscription_type }
58
+ its(:adapter) { should be adapter }
59
+ its(:destination) { should be destination }
60
+ its(:consumer) { should be consumer }
61
+
62
+ describe "#unsubscribe" do
63
+ it "makes it so messages don't go to the consumer any more" do
64
+ subscription.unsubscribe
65
+ expect {
66
+ destination.publish("should not be consumed")
67
+ }.to_not change{messages.size}
68
+ end
69
+ end
70
+ end
71
+
72
+ context "when there are already messages in the destination" do
73
+ before do
74
+ destination.publish(message1)
75
+ destination.publish(message2)
76
+ end
77
+
78
+ it "plays the messages into the consumer" do
79
+ expect {
80
+ subscription
81
+ pause_if_needed
82
+ }.to change{messages.size}.from(0).to(2)
83
+ bodies = messages.map(&:body)
84
+ expect(bodies).to include(message1)
85
+ expect(bodies).to include(message2)
86
+ end
87
+
88
+ it "removes the messages from the queue" do
89
+ pause_if_needed
90
+ expect {
91
+ subscription
92
+ pause_if_needed
93
+ }.to change{destination.message_count}.from(2).to(0)
94
+ end
95
+ end
96
+
97
+ context "when a message is published to the destination" do
98
+ before do
99
+ subscription
100
+ end
101
+
102
+ it "consumers the message into the consumer instead of putting them on the queue" do
103
+ expect {
104
+ expect {
105
+ subject.publish(destination, message1)
106
+ pause_if_needed
107
+ }.to change{messages.length}.from(0).to(1)
108
+ }.to_not change{destination.message_count}
109
+ expect(messages[0].body).to eq(message1)
110
+ end
111
+ end
112
+
113
+ context "when the consumer raises an error" do
114
+ let(:error) { RuntimeError.new("oh nos!") }
115
+ let(:consumer) do
116
+ lambda do |msg|
117
+ raise error
118
+ end
119
+ end
120
+
121
+ before do
122
+ destination.publish(message1)
123
+ destination.publish(message2)
124
+ end
125
+
126
+ it "keeps processing the messages" do
127
+ pause_if_needed
128
+ expect {
129
+ subscription
130
+ pause_if_needed
131
+ }.to change{destination.message_count}.from(2).to(0)
132
+ end
133
+
134
+ context "an error_handler is provided" do
135
+ let(:error_handler) { double(:error_handler, call: nil) }
136
+ let(:subscription) { adapter_context.subscribe(destination, error_handler: error_handler, &consumer) }
137
+
138
+ it "passes the errors and the messages to the error handler" do
139
+ subscription
140
+ pause_if_needed
141
+ expect(error_handler).to have_received(:call).with(error, kind_of(MessageDriver::Message::Base)).at_least(2).times
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,43 @@
1
+ shared_examples "transactions are not supported" do
2
+ describe "#supports_transactions?" do
3
+ it "returns false" do
4
+ expect(subject.supports_transactions?).to eq(false)
5
+ end
6
+ end
7
+ end
8
+
9
+ shared_examples "transactions are supported" do
10
+ describe "#supports_transactions?" do
11
+ it "returns true" do
12
+ expect(subject.supports_transactions?).to eq(true)
13
+ end
14
+ end
15
+
16
+ it { should respond_to :begin_transaction }
17
+ it { should respond_to :commit_transaction }
18
+ it { should respond_to :rollback_transaction }
19
+ it { should respond_to :in_transaction? }
20
+
21
+ describe "#in_transaction?" do
22
+ it "returns false if you aren't in a transaction" do
23
+ expect(subject.in_transaction?).to eq(false)
24
+ end
25
+ end
26
+
27
+ it "raises a MessageDriver::TransactionError error if you begin two transactions" do
28
+ subject.begin_transaction
29
+ expect {
30
+ subject.begin_transaction
31
+ }.to raise_error MessageDriver::TransactionError
32
+ end
33
+ it "raises a MessageDriver::TransactionError error if you commit outside of a transaction" do
34
+ expect {
35
+ subject.commit_transaction
36
+ }.to raise_error MessageDriver::TransactionError
37
+ end
38
+ it "raises a MessageDriver::TransactionError error if you rollback outside of a transaction" do
39
+ expect {
40
+ subject.rollback_transaction
41
+ }.to raise_error MessageDriver::TransactionError
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ module Utils
2
+ def pause_if_needed(seconds=0.1)
3
+ seconds *= 10 if ENV['CI'] == 'true'
4
+ case BrokerConfig.current_adapter
5
+ when :in_memory
6
+ else
7
+ sleep seconds
8
+ end
9
+ end
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.include Utils
14
+ end
@@ -2,43 +2,62 @@ require 'spec_helper'
2
2
 
3
3
  module MessageDriver::Adapters
4
4
  describe Base do
5
- class TestAdapter < described_class
5
+ class TestAdapter < Base
6
6
  def initialize(configuration)
7
-
8
- end
9
- end
10
- subject { TestAdapter.new({}) }
11
-
12
- describe "#publish" do
13
- it "raises an error" do
14
- expect {
15
- subject.publish(:destination, {foo: "bar"})
16
- }.to raise_error "Must be implemented in subclass"
17
7
  end
18
8
  end
9
+ subject(:adapter) { TestAdapter.new({}) }
19
10
 
20
- describe "#pop_message" do
11
+ describe "#new_context" do
21
12
  it "raises an error" do
22
13
  expect {
23
- subject.pop_message(:destination)
14
+ subject.new_context
24
15
  }.to raise_error "Must be implemented in subclass"
25
16
  end
26
17
  end
27
18
 
28
19
  describe "#stop" do
29
- it "raises an error" do
20
+ it "raises an error", pending: "maybe we don't want to do this" do
30
21
  expect {
31
22
  subject.stop
32
23
  }.to raise_error "Must be implemented in subclass"
33
24
  end
34
25
  end
35
26
 
36
- describe "#create_destination" do
37
- it "raises an error" do
38
- expect {
39
- subject.create_destination("foo")
40
- }.to raise_error "Must be implemented in subclass"
27
+ describe ContextBase do
28
+ class TestContext < ContextBase
41
29
  end
30
+ subject(:adapter_context) { TestContext.new(adapter) }
31
+
32
+ it_behaves_like "an adapter context"
33
+ it_behaves_like "transactions are not supported"
34
+ it_behaves_like "client acks are not supported"
35
+ it_behaves_like "subscriptions are not supported"
36
+
37
+ describe "#create_destination" do
38
+ it "raises an error" do
39
+ expect {
40
+ subject.create_destination("foo")
41
+ }.to raise_error "Must be implemented in subclass"
42
+ end
43
+ end
44
+
45
+ describe "#publish" do
46
+ it "raises an error" do
47
+ expect {
48
+ subject.publish(:destination, {foo: "bar"})
49
+ }.to raise_error "Must be implemented in subclass"
50
+ end
51
+ end
52
+
53
+ describe "#pop_message" do
54
+ it "raises an error" do
55
+ expect {
56
+ subject.pop_message(:destination)
57
+ }.to raise_error "Must be implemented in subclass"
58
+ end
59
+ end
60
+
42
61
  end
43
62
  end
44
63
  end
@@ -3,12 +3,16 @@ require 'message_driver/adapters/in_memory_adapter'
3
3
 
4
4
  module MessageDriver
5
5
  describe Broker do
6
- subject(:broker) { described_class.new(adapter: :in_memory) }
6
+ let(:options) { { adapter: :in_memory } }
7
+ before do
8
+ described_class.configure(options)
9
+ end
10
+ subject(:broker) { described_class.instance }
7
11
 
8
12
  describe ".configure" do
9
13
  it "calls new, passing in the options and saves the instance" do
10
14
  options = {foo: :bar}
11
- result = stub(described_class)
15
+ result = double(described_class)
12
16
  described_class.should_receive(:new).with(options).and_return(result)
13
17
 
14
18
  described_class.configure(options)
@@ -17,6 +21,24 @@ module MessageDriver
17
21
  end
18
22
  end
19
23
 
24
+ describe "#logger" do
25
+ it "returns the logger, which logs at the info level" do
26
+ expect(subject.logger).to be_a Logger
27
+ expect(subject.logger).to be_info
28
+ expect(subject.logger).to_not be_debug
29
+ end
30
+
31
+ context "configuring the logger" do
32
+ let(:logger) { double(Logger).as_null_object }
33
+ let(:options) { { adapter: :in_memory, logger: logger } }
34
+
35
+ it "returns the provided logger" do
36
+ actual = subject.logger
37
+ expect(actual).to be logger
38
+ end
39
+ end
40
+ end
41
+
20
42
  describe "#initialize" do
21
43
  it "raises an error if you don't specify an adapter" do
22
44
  expect {
@@ -62,23 +84,60 @@ module MessageDriver
62
84
  end
63
85
  end
64
86
 
65
- describe "#publish" do
66
- it "needs some real tests"
87
+ describe "#destination" do
88
+ it "returns the destination" do
89
+ destination = broker.destination(:my_queue, "my_queue", exclusive: true)
90
+ expect(destination).to be_a MessageDriver::Destination::Base
91
+ end
92
+ end
93
+
94
+ describe "#find_destination" do
95
+ it "finds the previously defined destination" do
96
+ my_destination = broker.destination(:my_queue, "my_queue", exclusive: true)
97
+ expect(broker.find_destination(:my_queue)).to be(my_destination)
98
+ end
67
99
 
68
100
  context "when the destination can't be found" do
69
- it "raises an error"
101
+ let(:bad_dest_name) { :not_a_queue }
102
+ it "raises a MessageDriver:NoSuchDestinationError" do
103
+ expect {
104
+ broker.find_destination(bad_dest_name)
105
+ }.to raise_error(MessageDriver::NoSuchDestinationError, /#{bad_dest_name}/)
106
+ end
70
107
  end
71
108
  end
72
- describe "#pop_message" do
73
- it "needs some real tests"
74
109
 
75
- context "when the destination can't be found" do
76
- it "raises an error"
110
+ describe "#consumer" do
111
+ let(:consumer_double) { lambda do |m| end }
112
+ it "saves the provided consumer" do
113
+ broker.consumer(:my_consumer, &consumer_double)
114
+ expect(broker.consumers[:my_consumer]).to be(consumer_double)
115
+ end
116
+
117
+ context "when no consumer is provided" do
118
+ it "raises an error" do
119
+ expect {
120
+ broker.consumer(:my_consumer)
121
+ }.to raise_error(MessageDriver::Error, "you must provide a block")
122
+ end
77
123
  end
78
124
  end
79
125
 
80
- describe "#destination" do
81
- it "needs some real tests"
126
+ describe "#find_consumer" do
127
+ let(:consumer_double) { lambda do |m| end }
128
+ it "finds the previously defined consumer" do
129
+ my_consumer = broker.consumer(:my_consumer, &consumer_double)
130
+ expect(broker.find_consumer(:my_consumer)).to be(my_consumer)
131
+ end
132
+
133
+ context "when the consumer can't be found" do
134
+ let(:bad_consumer_name) { :not_a_queue }
135
+ it "raises a MessageDriver:NoSuchConsumerError" do
136
+ expect {
137
+ broker.find_consumer(bad_consumer_name)
138
+ }.to raise_error(MessageDriver::NoSuchConsumerError, /#{bad_consumer_name}/)
139
+ end
140
+ end
82
141
  end
83
142
 
84
143
  describe "#dynamic_destination" do
@@ -86,13 +145,7 @@ module MessageDriver
86
145
  destination = broker.dynamic_destination("my_queue", exclusive: true)
87
146
  expect(destination).to be_a MessageDriver::Destination::Base
88
147
  end
89
- it "doesn't save the destination" do
90
- destination = nil
91
- expect {
92
- destination = broker.dynamic_destination("my_queue", exclusive: true)
93
- }.to_not change{broker.destinations.size}
94
- expect(broker.destinations.values).to_not include(destination)
95
- end
96
148
  end
149
+
97
150
  end
98
151
  end