bunny_mock 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +40 -0
- data/Guardfile +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +36 -0
- data/Rakefile +1 -0
- data/bunny_mock.gemspec +26 -0
- data/lib/bunny_mock.rb +143 -0
- data/lib/bunny_mock/version.rb +3 -0
- data/spec/bunny_mock_spec.rb +269 -0
- data/spec/lib/bunny_mock_spec.rb +247 -0
- data/spec/spec_helper.rb +8 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b8c27be071f36cc7392504c183e045abebff19e5
|
4
|
+
data.tar.gz: 28fd799d1f0deaf361f3efb4619e6fb7db304590
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e08ed554f967dd8e7fb7a6ae60152c4c4e6c01b9a8d9834f1de71398a86ab09002fde8d6ecac39e895463a4d1d60bd38c955829f551c217a4bc5aa122fe8b961
|
7
|
+
data.tar.gz: c41524efe2dbc129d9d857e59d28189e7642f2b2c5b12232e4544351a96b647a58bf9c270038bc286da4dc017c480f9b14d95ebc68ff77d3ee045b50be0d4ac6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bunny_mock (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.4)
|
10
|
+
given_core (3.1.1)
|
11
|
+
sorcerer (>= 0.3.7)
|
12
|
+
multi_json (1.8.0)
|
13
|
+
rake (10.1.0)
|
14
|
+
rspec (2.14.1)
|
15
|
+
rspec-core (~> 2.14.0)
|
16
|
+
rspec-expectations (~> 2.14.0)
|
17
|
+
rspec-mocks (~> 2.14.0)
|
18
|
+
rspec-core (2.14.5)
|
19
|
+
rspec-expectations (2.14.3)
|
20
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
21
|
+
rspec-given (3.1.1)
|
22
|
+
given_core (= 3.1.1)
|
23
|
+
rspec (>= 2.12)
|
24
|
+
rspec-mocks (2.14.3)
|
25
|
+
simplecov (0.7.1)
|
26
|
+
multi_json (~> 1.0)
|
27
|
+
simplecov-html (~> 0.7.1)
|
28
|
+
simplecov-html (0.7.1)
|
29
|
+
sorcerer (1.0.2)
|
30
|
+
|
31
|
+
PLATFORMS
|
32
|
+
ruby
|
33
|
+
|
34
|
+
DEPENDENCIES
|
35
|
+
bundler (~> 1.3)
|
36
|
+
bunny_mock!
|
37
|
+
rake
|
38
|
+
rspec
|
39
|
+
rspec-given
|
40
|
+
simplecov
|
data/Guardfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
notification :emacs
|
2
|
+
notification :terminal
|
3
|
+
|
4
|
+
group :all do
|
5
|
+
guard :rspec do
|
6
|
+
watch(%r{^spec/.+_spec\.rb$})
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { "spec" }
|
9
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
group :unit do
|
14
|
+
guard :rspec, :cli => '--tag ~integration' do
|
15
|
+
watch(%r{^spec/lib/.+_spec\.rb$})
|
16
|
+
watch('spec/spec_helper.rb') { "spec" }
|
17
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
18
|
+
end
|
19
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 svs
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
This is a brain-dead-simple mock for the `Bunny` class provided by the [bunny gem](https://github.com/ruby-amqp/bunny), which is a synchronous Ruby RabbitMQ client. If you want to mock out RabbitMQ in your tests and are currently using Bunny, this might be the tool for you.
|
4
|
+
|
5
|
+
BunnyMock does not mock all of the methods of Bunny. It currently only mocks the behavior I needed for my immediate needs, which is mainly creating and binding queues and exchanges, and publishing/subscribing messages.
|
6
|
+
|
7
|
+
Feel free to fork it to add more behavior mocking and send me a pull request.
|
8
|
+
|
9
|
+
# Installation
|
10
|
+
|
11
|
+
The easiest way to use this is to drop bunny_mock.rb into your `spec/support` directory, or something like that. Just require bunny_mock and then use `BunnyMock.new` instead of `Bunny.new(params)`.
|
12
|
+
|
13
|
+
Someday I might package this up as a gem.
|
14
|
+
|
15
|
+
|
16
|
+
# Usage
|
17
|
+
|
18
|
+
Since this is intended as a simple way to help test your collaboration with Bunny/RabbitMQ, it does not really opereate as a real queue, but it _does_ support receiving messages into a queue, and reading them out. The main thing to be aware of is that the `BunnyMock::Queue#subscribe` method does not block waiting for messages, consumes all queued messages, and returns when there are no more messages. This differs from the behavior of the real Bunny.
|
19
|
+
|
20
|
+
See the first "integration" test case in `spec/lib/bunny_mock_spec.rb` for a quick example of how to use BunnyMock.
|
21
|
+
|
22
|
+
# Author
|
23
|
+
|
24
|
+
Scott W. Bradley - http://scottwb.com
|
25
|
+
|
26
|
+
# Contributing
|
27
|
+
|
28
|
+
* Fork the project.
|
29
|
+
* Make your feature addtion or bug fix.
|
30
|
+
* Add test for it. This is important so I don't break it in a future version unintentionally.
|
31
|
+
* Commit, do not mess with rakefile, version, or history. (If you want to have your own version, that is fine, but bump version in a separate commit by itself so I can ignore it when I pull).
|
32
|
+
* Send me a pull request. Bonus points for topic branches.
|
33
|
+
|
34
|
+
# License
|
35
|
+
|
36
|
+
This code is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bunny_mock.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bunny_mock/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bunny_mock"
|
8
|
+
spec.version = BunnyMock::VERSION
|
9
|
+
spec.authors = ["svs"]
|
10
|
+
spec.email = ["svs@svs.io"]
|
11
|
+
spec.description = %q{Mocking library for Bunny}
|
12
|
+
spec.summary = %q{Easily mock the bunny gem and pretend you have RabbitMQ running. }
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "rspec-given"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
end
|
data/lib/bunny_mock.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require "bunny_mock/version"
|
2
|
+
|
3
|
+
class BunnyMock
|
4
|
+
|
5
|
+
def start
|
6
|
+
:connected
|
7
|
+
end
|
8
|
+
|
9
|
+
def qos
|
10
|
+
:qos_ok
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def channels
|
18
|
+
@channels ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_channel
|
22
|
+
Channel.new.tap{|c| channels << c}
|
23
|
+
end
|
24
|
+
|
25
|
+
def queue(*attrs)
|
26
|
+
BunnyMock::Queue.new(*attrs)
|
27
|
+
end
|
28
|
+
|
29
|
+
def exchange(*attrs)
|
30
|
+
BunnyMock::Exchange.new(*attrs)
|
31
|
+
end
|
32
|
+
|
33
|
+
class Consumer
|
34
|
+
attr_accessor :message_count
|
35
|
+
def initialize(c)
|
36
|
+
self.message_count = c
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Channel
|
41
|
+
attr_reader :queues
|
42
|
+
def queue(name, attrs = {})
|
43
|
+
@queues ||= []
|
44
|
+
Queue.new(name, attrs).tap { |q| @queues << q }
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
class Queue
|
51
|
+
attr_accessor :name, :attrs, :messages, :delivery_count
|
52
|
+
def initialize(name, attrs = {})
|
53
|
+
self.name = name
|
54
|
+
self.attrs = attrs.dup
|
55
|
+
self.messages = []
|
56
|
+
self.delivery_count = 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def bind(exchange)
|
60
|
+
exchange.queues << self
|
61
|
+
end
|
62
|
+
|
63
|
+
# Note that this doesn't block waiting for messages like the real world.
|
64
|
+
def subscribe(*args, &block)
|
65
|
+
while message = messages.shift
|
66
|
+
self.delivery_count += 1
|
67
|
+
yield({:payload => message})
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def publish(msg)
|
72
|
+
self.messages << msg
|
73
|
+
end
|
74
|
+
|
75
|
+
def default_consumer
|
76
|
+
BunnyMock::Consumer.new(self.delivery_count)
|
77
|
+
end
|
78
|
+
|
79
|
+
# NOTE: This is NOT a method that is supported on real Bunny queues.
|
80
|
+
# This is a custom method to get us a deep copy of
|
81
|
+
# all the messages currently in the queue. This is provided
|
82
|
+
# to aid in testing a system where it is not practical for the
|
83
|
+
# test to subscribe to the queue and read the messages, but we
|
84
|
+
# need to verify that certain messages have been published.
|
85
|
+
def snapshot_messages
|
86
|
+
Marshal.load(Marshal.dump(messages))
|
87
|
+
end
|
88
|
+
|
89
|
+
def method_missing(method, *args)
|
90
|
+
method_name = method.to_s
|
91
|
+
is_predicate = false
|
92
|
+
if method_name =~ /^(.*)\?$/
|
93
|
+
key = $1.to_sym
|
94
|
+
is_predicate = true
|
95
|
+
else
|
96
|
+
key = method.to_sym
|
97
|
+
end
|
98
|
+
|
99
|
+
if attrs.has_key? key
|
100
|
+
value = attrs[key]
|
101
|
+
is_predicate ? !!value : value
|
102
|
+
else
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Exchange
|
109
|
+
attr_accessor :name, :attrs, :queues
|
110
|
+
def initialize(name, attrs = {})
|
111
|
+
self.name = name
|
112
|
+
self.attrs = attrs.dup
|
113
|
+
self.queues = []
|
114
|
+
end
|
115
|
+
|
116
|
+
def publish(msg, msg_attrs = {})
|
117
|
+
queues.each { |q| q.messages << msg }
|
118
|
+
end
|
119
|
+
|
120
|
+
def bound_to?(queue_name)
|
121
|
+
queues.any?{|q| q.name == queue_name}
|
122
|
+
end
|
123
|
+
|
124
|
+
def method_missing(method, *args)
|
125
|
+
method_name = method.to_s
|
126
|
+
is_predicate = false
|
127
|
+
if method_name =~ /^(.*)\?$/
|
128
|
+
key = $1.to_sym
|
129
|
+
is_predicate = true
|
130
|
+
else
|
131
|
+
key = method.to_sym
|
132
|
+
end
|
133
|
+
|
134
|
+
if attrs.has_key? key
|
135
|
+
value = attrs[key]
|
136
|
+
is_predicate ? !!value : value
|
137
|
+
else
|
138
|
+
super
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bunny_mock'
|
3
|
+
|
4
|
+
describe "BunnyMock Integration Tests", :integration => true do
|
5
|
+
it "should handle the basics of message passing" do
|
6
|
+
# Basic one-to-one queue/exchange setup.
|
7
|
+
bunny = BunnyMock.new
|
8
|
+
queue = bunny.queue(
|
9
|
+
"integration_queue",
|
10
|
+
:durable => true,
|
11
|
+
:auto_delete => true,
|
12
|
+
:exclusive => false,
|
13
|
+
:arguments => {"x-ha-policy" => "all"}
|
14
|
+
)
|
15
|
+
exchange = bunny.exchange(
|
16
|
+
"integration_exchange",
|
17
|
+
:type => :direct,
|
18
|
+
:durable => true,
|
19
|
+
:auto_delete => true
|
20
|
+
)
|
21
|
+
queue.bind(exchange)
|
22
|
+
|
23
|
+
# Basic assertions
|
24
|
+
bunny.channels.should be_empty
|
25
|
+
queue.messages.should be_empty
|
26
|
+
exchange.queues.should have(1).queue
|
27
|
+
exchange.should be_bound_to "integration_queue"
|
28
|
+
queue.default_consumer.message_count.should == 0
|
29
|
+
|
30
|
+
# Send some messages
|
31
|
+
exchange.publish("Message 1")
|
32
|
+
exchange.publish("Message 2")
|
33
|
+
exchange.publish("Message 3")
|
34
|
+
|
35
|
+
# Verify state of the queue
|
36
|
+
queue.messages.should have(3).messages
|
37
|
+
queue.messages.should == [
|
38
|
+
"Message 1",
|
39
|
+
"Message 2",
|
40
|
+
"Message 3"
|
41
|
+
]
|
42
|
+
queue.snapshot_messages.should have(3).messages
|
43
|
+
queue.snapshot_messages.should == [
|
44
|
+
"Message 1",
|
45
|
+
"Message 2",
|
46
|
+
"Message 3"
|
47
|
+
]
|
48
|
+
|
49
|
+
# Here's what we expect to happen when we subscribe to this queue.
|
50
|
+
handler = double("target")
|
51
|
+
handler.should_receive(:handle_message).with("Message 1").ordered
|
52
|
+
handler.should_receive(:handle_message).with("Message 2").ordered
|
53
|
+
handler.should_receive(:handle_message).with("Message 3").ordered
|
54
|
+
|
55
|
+
# Read all those messages
|
56
|
+
msg_count = 0
|
57
|
+
queue.subscribe do |msg|
|
58
|
+
handler.handle_message(msg[:payload])
|
59
|
+
msg_count += 1
|
60
|
+
queue.default_consumer.message_count.should == msg_count
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe BunnyMock do
|
66
|
+
Given(:bunny) { BunnyMock.new }
|
67
|
+
|
68
|
+
describe "#start" do
|
69
|
+
Then { bunny.start.should == :connected }
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#qos" do
|
73
|
+
Then { bunny.qos.should == :qos_ok }
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#stop" do
|
77
|
+
Then { bunny.stop.should be_nil }
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#channels" do
|
81
|
+
context "at the start" do
|
82
|
+
Then { bunny.channels.should be_an Array }
|
83
|
+
Then { bunny.channels.should be_empty }
|
84
|
+
end
|
85
|
+
context "adding channels" do
|
86
|
+
When(:channel) { bunny.create_channel }
|
87
|
+
Then { bunny.channels.count.should == 1 }
|
88
|
+
end
|
89
|
+
describe "channel queues" do
|
90
|
+
Given(:c) { bunny.create_channel }
|
91
|
+
When(:queues) {
|
92
|
+
c.queue("foo", {:bar => :baz})
|
93
|
+
}
|
94
|
+
Then { c.queues.first.should be_a BunnyMock::Queue }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#queue" do
|
99
|
+
When(:queue) { bunny.queue("my_queue", :durable => true) }
|
100
|
+
Then { queue.should be_a BunnyMock::Queue }
|
101
|
+
Then { queue.name.should == "my_queue" }
|
102
|
+
Then { queue.should be_durable }
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#exchange" do
|
106
|
+
When(:exchange) { bunny.exchange("my_exch", :type => :direct) }
|
107
|
+
Then { exchange.should be_a BunnyMock::Exchange }
|
108
|
+
Then { exchange.name.should == "my_exch" }
|
109
|
+
Then { exchange.type.should == :direct }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe BunnyMock::Consumer do
|
114
|
+
describe "#message_count" do
|
115
|
+
Given(:consumer) { BunnyMock::Consumer.new(5) }
|
116
|
+
Then { consumer.message_count.should == 5 }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe BunnyMock::Queue do
|
121
|
+
Given(:queue_name) { "my_test_queue" }
|
122
|
+
Given(:queue_attrs) {
|
123
|
+
{
|
124
|
+
:durable => true,
|
125
|
+
:auto_delete => true,
|
126
|
+
:exclusive => false,
|
127
|
+
:arguments => {"x-ha-policy" => "all"}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
Given(:queue) { BunnyMock::Queue.new(queue_name, queue_attrs) }
|
131
|
+
|
132
|
+
describe "#name" do
|
133
|
+
Then { queue.name.should == queue_name }
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "#attrs" do
|
137
|
+
Then { queue.attrs.should == queue_attrs }
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "#messages" do
|
141
|
+
Then { queue.messages.should be_an Array }
|
142
|
+
Then { queue.messages.should be_empty }
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#snapshot_messages" do
|
146
|
+
Then { queue.snapshot_messages.should be_an Array }
|
147
|
+
Then { queue.snapshot_messages.should be_empty }
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "#delivery_count" do
|
151
|
+
Then { queue.delivery_count.should == 0 }
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#subscribe" do
|
155
|
+
Given { queue.messages = ["Ehh", "What's up Doc?"] }
|
156
|
+
Given(:handler) { double("handler") }
|
157
|
+
Given {
|
158
|
+
handler.should_receive(:handle).with("Ehh").ordered
|
159
|
+
handler.should_receive(:handle).with("What's up Doc?").ordered
|
160
|
+
}
|
161
|
+
When { queue.subscribe { |msg| handler.handle(msg[:payload]) } }
|
162
|
+
Then { queue.messages.should be_empty }
|
163
|
+
Then { queue.snapshot_messages.should be_empty }
|
164
|
+
Then { queue.delivery_count.should == 2 }
|
165
|
+
Then { verify_mocks_for_rspec }
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#snapshot_messages" do
|
169
|
+
Given { queue.messages = ["Ehh", "What's up Doc?"] }
|
170
|
+
Then {
|
171
|
+
snapshot = queue.snapshot_messages
|
172
|
+
snapshot.should == ["Ehh", "What's up Doc?"]
|
173
|
+
snapshot.shift
|
174
|
+
snapshot << "Nothin"
|
175
|
+
snapshot.should == ["What's up Doc?", "Nothin"]
|
176
|
+
queue.messages.should == ["Ehh", "What's up Doc?"]
|
177
|
+
queue.snapshot_messages.should == ["Ehh", "What's up Doc?"]
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#bind" do
|
182
|
+
Given(:exchange) { BunnyMock::Exchange.new("my_test_exchange",) }
|
183
|
+
When { queue.bind(exchange) }
|
184
|
+
Then { exchange.should be_bound_to "my_test_queue" }
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "#default_consumer" do
|
188
|
+
Given { queue.delivery_count = 5 }
|
189
|
+
When(:consumer) { queue.default_consumer }
|
190
|
+
Then { consumer.should be_a BunnyMock::Consumer }
|
191
|
+
Then { consumer.message_count.should == 5 }
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "#method_missing" do
|
195
|
+
Then { queue.durable.should be_true }
|
196
|
+
Then { queue.should be_durable }
|
197
|
+
Then { queue.auto_delete.should be_true }
|
198
|
+
Then { queue.should be_auto_delete }
|
199
|
+
Then { queue.exclusive.should == false }
|
200
|
+
Then { queue.should_not be_exclusive }
|
201
|
+
Then { queue.arguments.should == {"x-ha-policy" => "all"} }
|
202
|
+
Then { expect { queue.wtf }.to raise_error NoMethodError }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe BunnyMock::Exchange do
|
207
|
+
Given(:exchange_name) { "my_test_exchange" }
|
208
|
+
Given(:exchange_attrs) {
|
209
|
+
{
|
210
|
+
:type => :direct,
|
211
|
+
:durable => true,
|
212
|
+
:auto_delete => true
|
213
|
+
}
|
214
|
+
}
|
215
|
+
Given(:exchange) { BunnyMock::Exchange.new(exchange_name, exchange_attrs) }
|
216
|
+
|
217
|
+
describe "#name" do
|
218
|
+
Then { exchange.name.should == exchange_name }
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "#attrs" do
|
222
|
+
Then { exchange.attrs.should == exchange_attrs }
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "#queues" do
|
226
|
+
context "when the exchange is not bound to any queues" do
|
227
|
+
Then { exchange.queues.should be_an Array }
|
228
|
+
Then { exchange.queues.should be_empty }
|
229
|
+
end
|
230
|
+
|
231
|
+
context "when the exchange is bound to a queue" do
|
232
|
+
Given(:queue) { BunnyMock::Queue.new("a_queue") }
|
233
|
+
Given { queue.bind(exchange) }
|
234
|
+
Then { exchange.queues.should have(1).queue }
|
235
|
+
Then { exchange.queues.first.should == queue }
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "#bound_to?" do
|
240
|
+
Given(:queue) { BunnyMock::Queue.new("a_queue") }
|
241
|
+
Given { queue.bind(exchange) }
|
242
|
+
Then { exchange.should be_bound_to("a_queue") }
|
243
|
+
Then { exchange.should_not be_bound_to("another_queue") }
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "#publish" do
|
247
|
+
Given(:queue1) { BunnyMock::Queue.new("queue1") }
|
248
|
+
Given(:queue2) { BunnyMock::Queue.new("queue2") }
|
249
|
+
Given { queue1.bind(exchange) }
|
250
|
+
Given { queue2.bind(exchange) }
|
251
|
+
When { exchange.publish("hello") }
|
252
|
+
Then { queue1.messages.should == ["hello"] }
|
253
|
+
Then { queue1.snapshot_messages.should == ["hello"] }
|
254
|
+
Then { queue2.messages.should == ["hello"] }
|
255
|
+
Then { queue2.snapshot_messages.should == ["hello"] }
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "#method_missing" do
|
259
|
+
Then { exchange.type.should == :direct }
|
260
|
+
Then { exchange.durable.should be_true }
|
261
|
+
Then { exchange.should be_durable }
|
262
|
+
Then { exchange.auto_delete.should be_true }
|
263
|
+
Then { exchange.should be_auto_delete }
|
264
|
+
Then { expect { exchange.wtf }.to raise_error NoMethodError }
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bunny_mock'
|
3
|
+
|
4
|
+
describe "BunnyMock Integration Tests", :integration => true do
|
5
|
+
it "should handle the basics of message passing" do
|
6
|
+
# Basic one-to-one queue/exchange setup.
|
7
|
+
bunny = BunnyMock.new
|
8
|
+
queue = bunny.queue(
|
9
|
+
"integration_queue",
|
10
|
+
:durable => true,
|
11
|
+
:auto_delete => true,
|
12
|
+
:exclusive => false,
|
13
|
+
:arguments => {"x-ha-policy" => "all"}
|
14
|
+
)
|
15
|
+
exchange = bunny.exchange(
|
16
|
+
"integration_exchange",
|
17
|
+
:type => :direct,
|
18
|
+
:durable => true,
|
19
|
+
:auto_delete => true
|
20
|
+
)
|
21
|
+
queue.bind(exchange)
|
22
|
+
|
23
|
+
# Basic assertions
|
24
|
+
queue.messages.should be_empty
|
25
|
+
exchange.queues.should have(1).queue
|
26
|
+
exchange.should be_bound_to "integration_queue"
|
27
|
+
queue.default_consumer.message_count.should == 0
|
28
|
+
|
29
|
+
# Send some messages
|
30
|
+
exchange.publish("Message 1")
|
31
|
+
exchange.publish("Message 2")
|
32
|
+
exchange.publish("Message 3")
|
33
|
+
|
34
|
+
# Verify state of the queue
|
35
|
+
queue.messages.should have(3).messages
|
36
|
+
queue.messages.should == [
|
37
|
+
"Message 1",
|
38
|
+
"Message 2",
|
39
|
+
"Message 3"
|
40
|
+
]
|
41
|
+
queue.snapshot_messages.should have(3).messages
|
42
|
+
queue.snapshot_messages.should == [
|
43
|
+
"Message 1",
|
44
|
+
"Message 2",
|
45
|
+
"Message 3"
|
46
|
+
]
|
47
|
+
|
48
|
+
# Here's what we expect to happen when we subscribe to this queue.
|
49
|
+
handler = mock("target")
|
50
|
+
handler.should_receive(:handle_message).with("Message 1").ordered
|
51
|
+
handler.should_receive(:handle_message).with("Message 2").ordered
|
52
|
+
handler.should_receive(:handle_message).with("Message 3").ordered
|
53
|
+
|
54
|
+
# Read all those messages
|
55
|
+
msg_count = 0
|
56
|
+
queue.subscribe do |msg|
|
57
|
+
handler.handle_message(msg[:payload])
|
58
|
+
msg_count += 1
|
59
|
+
queue.default_consumer.message_count.should == msg_count
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe BunnyMock do
|
65
|
+
Given(:bunny) { BunnyMock.new }
|
66
|
+
|
67
|
+
describe "#start" do
|
68
|
+
Then { bunny.start.should == :connected }
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#qos" do
|
72
|
+
Then { bunny.qos.should == :qos_ok }
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#stop" do
|
76
|
+
Then { bunny.stop.should be_nil }
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#queue" do
|
80
|
+
When(:queue) { bunny.queue("my_queue", :durable => true) }
|
81
|
+
Then { queue.should be_a BunnyMock::Queue }
|
82
|
+
Then { queue.name.should == "my_queue" }
|
83
|
+
Then { queue.should be_durable }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#exchange" do
|
87
|
+
When(:exchange) { bunny.exchange("my_exch", :type => :direct) }
|
88
|
+
Then { exchange.should be_a BunnyMock::Exchange }
|
89
|
+
Then { exchange.name.should == "my_exch" }
|
90
|
+
Then { exchange.type.should == :direct }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe BunnyMock::Consumer do
|
95
|
+
describe "#message_count" do
|
96
|
+
Given(:consumer) { BunnyMock::Consumer.new(5) }
|
97
|
+
Then { consumer.message_count.should == 5 }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe BunnyMock::Queue do
|
102
|
+
Given(:queue_name) { "my_test_queue" }
|
103
|
+
Given(:queue_attrs) {
|
104
|
+
{
|
105
|
+
:durable => true,
|
106
|
+
:auto_delete => true,
|
107
|
+
:exclusive => false,
|
108
|
+
:arguments => {"x-ha-policy" => "all"}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
Given(:queue) { BunnyMock::Queue.new(queue_name, queue_attrs) }
|
112
|
+
|
113
|
+
describe "#name" do
|
114
|
+
Then { queue.name.should == queue_name }
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#attrs" do
|
118
|
+
Then { queue.attrs.should == queue_attrs }
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#messages" do
|
122
|
+
Then { queue.messages.should be_an Array }
|
123
|
+
Then { queue.messages.should be_empty }
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#snapshot_messages" do
|
127
|
+
Then { queue.snapshot_messages.should be_an Array }
|
128
|
+
Then { queue.snapshot_messages.should be_empty }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#delivery_count" do
|
132
|
+
Then { queue.delivery_count.should == 0 }
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#subscribe" do
|
136
|
+
Given { queue.messages = ["Ehh", "What's up Doc?"] }
|
137
|
+
Given(:handler) { mock("handler") }
|
138
|
+
Given {
|
139
|
+
handler.should_receive(:handle).with("Ehh").ordered
|
140
|
+
handler.should_receive(:handle).with("What's up Doc?").ordered
|
141
|
+
}
|
142
|
+
When { queue.subscribe { |msg| handler.handle(msg[:payload]) } }
|
143
|
+
Then { queue.messages.should be_empty }
|
144
|
+
Then { queue.snapshot_messages.should be_empty }
|
145
|
+
Then { queue.delivery_count.should == 2 }
|
146
|
+
Then { verify_mocks_for_rspec }
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#snapshot_messages" do
|
150
|
+
Given { queue.messages = ["Ehh", "What's up Doc?"] }
|
151
|
+
Then {
|
152
|
+
snapshot = queue.snapshot_messages
|
153
|
+
snapshot.should == ["Ehh", "What's up Doc?"]
|
154
|
+
snapshot.shift
|
155
|
+
snapshot << "Nothin"
|
156
|
+
snapshot.should == ["What's up Doc?", "Nothin"]
|
157
|
+
queue.messages.should == ["Ehh", "What's up Doc?"]
|
158
|
+
queue.snapshot_messages.should == ["Ehh", "What's up Doc?"]
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#bind" do
|
163
|
+
Given(:exchange) { BunnyMock::Exchange.new("my_test_exchange",) }
|
164
|
+
When { queue.bind(exchange) }
|
165
|
+
Then { exchange.should be_bound_to "my_test_queue" }
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#default_consumer" do
|
169
|
+
Given { queue.delivery_count = 5 }
|
170
|
+
When(:consumer) { queue.default_consumer }
|
171
|
+
Then { consumer.should be_a BunnyMock::Consumer }
|
172
|
+
Then { consumer.message_count.should == 5 }
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "#method_missing" do
|
176
|
+
Then { queue.durable.should be_true }
|
177
|
+
Then { queue.should be_durable }
|
178
|
+
Then { queue.auto_delete.should be_true }
|
179
|
+
Then { queue.should be_auto_delete }
|
180
|
+
Then { queue.exclusive.should == false }
|
181
|
+
Then { queue.should_not be_exclusive }
|
182
|
+
Then { queue.arguments.should == {"x-ha-policy" => "all"} }
|
183
|
+
Then { expect { queue.wtf }.to raise_error NoMethodError }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe BunnyMock::Exchange do
|
188
|
+
Given(:exchange_name) { "my_test_exchange" }
|
189
|
+
Given(:exchange_attrs) {
|
190
|
+
{
|
191
|
+
:type => :direct,
|
192
|
+
:durable => true,
|
193
|
+
:auto_delete => true
|
194
|
+
}
|
195
|
+
}
|
196
|
+
Given(:exchange) { BunnyMock::Exchange.new(exchange_name, exchange_attrs) }
|
197
|
+
|
198
|
+
describe "#name" do
|
199
|
+
Then { exchange.name.should == exchange_name }
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "#attrs" do
|
203
|
+
Then { exchange.attrs.should == exchange_attrs }
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#queues" do
|
207
|
+
context "when the exchange is not bound to any queues" do
|
208
|
+
Then { exchange.queues.should be_an Array }
|
209
|
+
Then { exchange.queues.should be_empty }
|
210
|
+
end
|
211
|
+
|
212
|
+
context "when the exchange is bound to a queue" do
|
213
|
+
Given(:queue) { BunnyMock::Queue.new("a_queue") }
|
214
|
+
Given { queue.bind(exchange) }
|
215
|
+
Then { exchange.queues.should have(1).queue }
|
216
|
+
Then { exchange.queues.first.should == queue }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "#bound_to?" do
|
221
|
+
Given(:queue) { BunnyMock::Queue.new("a_queue") }
|
222
|
+
Given { queue.bind(exchange) }
|
223
|
+
Then { exchange.should be_bound_to("a_queue") }
|
224
|
+
Then { exchange.should_not be_bound_to("another_queue") }
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "#publish" do
|
228
|
+
Given(:queue1) { BunnyMock::Queue.new("queue1") }
|
229
|
+
Given(:queue2) { BunnyMock::Queue.new("queue2") }
|
230
|
+
Given { queue1.bind(exchange) }
|
231
|
+
Given { queue2.bind(exchange) }
|
232
|
+
When { exchange.publish("hello") }
|
233
|
+
Then { queue1.messages.should == ["hello"] }
|
234
|
+
Then { queue1.snapshot_messages.should == ["hello"] }
|
235
|
+
Then { queue2.messages.should == ["hello"] }
|
236
|
+
Then { queue2.snapshot_messages.should == ["hello"] }
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "#method_missing" do
|
240
|
+
Then { exchange.type.should == :direct }
|
241
|
+
Then { exchange.durable.should be_true }
|
242
|
+
Then { exchange.should be_durable }
|
243
|
+
Then { exchange.auto_delete.should be_true }
|
244
|
+
Then { exchange.should be_auto_delete }
|
245
|
+
Then { expect { exchange.wtf }.to raise_error NoMethodError }
|
246
|
+
end
|
247
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bunny_mock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- svs
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-given
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Mocking library for Bunny
|
84
|
+
email:
|
85
|
+
- svs@svs.io
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- Guardfile
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bunny_mock.gemspec
|
99
|
+
- lib/bunny_mock.rb
|
100
|
+
- lib/bunny_mock/version.rb
|
101
|
+
- spec/bunny_mock_spec.rb
|
102
|
+
- spec/lib/bunny_mock_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
homepage: ''
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.1.9
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Easily mock the bunny gem and pretend you have RabbitMQ running.
|
128
|
+
test_files:
|
129
|
+
- spec/bunny_mock_spec.rb
|
130
|
+
- spec/lib/bunny_mock_spec.rb
|
131
|
+
- spec/spec_helper.rb
|