better_receive 0.2.0 → 0.3.0
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.
- data/README.md +20 -11
- data/better_receive.gemspec +2 -2
- data/lib/better_receive/mock.rb +36 -37
- data/lib/better_receive/version.rb +1 -1
- data/lib/better_receive.rb +2 -2
- data/spec/lib/better_receive/mock_spec.rb +102 -0
- data/spec/lib/better_receive_spec.rb +8 -81
- metadata +5 -3
data/README.md
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
# BetterReceive
|
2
2
|
|
3
|
-
|
3
|
+
BetterReceive helps test drive new functionality and prevent bugs by asserting that an object responds to a method before mocking it.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
$ gem install better_receive
|
8
8
|
|
9
|
-
|
9
|
+
## Usage
|
10
10
|
|
11
|
-
And then execute:
|
12
11
|
|
13
|
-
|
12
|
+
```ruby
|
13
|
+
class Foo; end
|
14
|
+
foo = Foo.new
|
14
15
|
|
15
|
-
|
16
|
+
foo.better_receive(:bar)
|
17
|
+
```
|
18
|
+
or
|
19
|
+
```ruby
|
20
|
+
Foo.any_instance.better_receive(:bar)
|
21
|
+
```
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
TODO: Write usage instructions here
|
23
|
+
Either situation will raise an error because instances of Foo do not respond to :bar.
|
22
24
|
|
23
25
|
## Contributing
|
24
26
|
|
@@ -27,3 +29,10 @@ TODO: Write usage instructions here
|
|
27
29
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
30
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
31
|
5. Create new Pull Request
|
32
|
+
|
33
|
+
## To Do
|
34
|
+
|
35
|
+
* #better_stub
|
36
|
+
* support arrity checks with #responds_to
|
37
|
+
* support options other than Ruby 1.9.2+ and RSpec
|
38
|
+
|
data/better_receive.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["Steve Ellis", "Matthew Horan"]
|
6
6
|
gem.email = ["email@steveell.is", "matt@matthoran.com"]
|
7
7
|
gem.description = %q{Assert that an object responds to a method before asserting that the method is received.}
|
8
|
-
gem.summary = %q{A
|
8
|
+
gem.summary = %q{A more assertive mock.}
|
9
9
|
gem.homepage = "http://github.com/se3000/better_receive"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
14
|
gem.name = "better_receive"
|
15
15
|
gem.require_paths = ["lib"]
|
16
|
-
gem.version = BetterReceive::
|
16
|
+
gem.version = BetterReceive::BETTER_VERSION
|
17
17
|
|
18
18
|
gem.add_dependency("rspec", "~> 2.0")
|
19
19
|
gem.add_development_dependency("rake", ">= 0")
|
data/lib/better_receive/mock.rb
CHANGED
@@ -1,65 +1,64 @@
|
|
1
1
|
module BetterReceive
|
2
2
|
class Mock
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@
|
4
|
+
def initialize(subject)
|
5
|
+
@subject = subject
|
6
6
|
end
|
7
7
|
|
8
|
-
def responds_to_and_receives(selector, options, &block)
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def responds_to_and_receives(selector, options={}, &block)
|
9
|
+
if subject.is_a?(RSpec::Mocks::AnyInstance::Recorder)
|
10
|
+
any_instance_better_receive(selector, options, &block)
|
11
|
+
else
|
12
|
+
subject.should respond_to selector
|
13
|
+
mock_subject_method(selector, options, &block)
|
14
|
+
end
|
12
15
|
end
|
13
16
|
|
14
|
-
def rspec_verify
|
15
|
-
end
|
16
17
|
|
17
18
|
private
|
18
19
|
|
19
|
-
attr_reader :
|
20
|
+
attr_reader :subject
|
20
21
|
|
21
|
-
def
|
22
|
-
|
23
|
-
when RSpec::Mocks::AnyInstance::Recorder
|
24
|
-
any_instance_should_respond_to selector
|
25
|
-
else
|
26
|
-
object.should respond_to(selector)
|
27
|
-
end
|
22
|
+
def respond_to(selector)
|
23
|
+
RSpec::Matchers::BuiltIn::RespondTo.new(selector)
|
28
24
|
end
|
29
25
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
raise "Expected instances of #{klass.name} to respond to :#{selector}"
|
34
|
-
end
|
26
|
+
def mock_subject_method(selector, options, &block)
|
27
|
+
location = options[:expected_from] || caller(1)[2]
|
28
|
+
subject_mock_proxy.add_message_expectation(location, selector, options, &block)
|
35
29
|
end
|
36
30
|
|
37
|
-
def
|
38
|
-
|
31
|
+
def subject_mock_proxy
|
32
|
+
@mock_proxy ||= subject.send(:__mock_proxy)
|
39
33
|
end
|
40
34
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
35
|
+
def any_instance_better_receive(selector, options, &block)
|
36
|
+
any_instance_should_respond_to selector
|
37
|
+
any_instance_should_receive selector, &block
|
38
|
+
end
|
39
|
+
|
40
|
+
def any_instance_should_respond_to(selector)
|
41
|
+
klass = subject.instance_variable_get(:@klass)
|
42
|
+
unless klass.method_defined?(selector)
|
43
|
+
raise "Expected instances of #{klass.name} to respond to :#{selector}"
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
51
47
|
def any_instance_should_receive(selector, &block)
|
52
|
-
RSpec::Mocks::space.add(
|
48
|
+
RSpec::Mocks::space.add(subject)
|
53
49
|
|
54
|
-
|
55
|
-
|
50
|
+
subject.instance_variable_set(:@expectation_set, true)
|
51
|
+
subject.send(:observe!, selector)
|
56
52
|
|
57
|
-
|
58
|
-
object.message_chains.add(selector, expectation_chain)
|
53
|
+
subject.message_chains.add(selector, expectation_chain(selector, &block))
|
59
54
|
end
|
60
55
|
|
61
|
-
def
|
62
|
-
|
56
|
+
def expectation_chain(*args)
|
57
|
+
if defined?(RSpec::Mocks::AnyInstance::PositiveExpectationChain)
|
58
|
+
RSpec::Mocks::AnyInstance::PositiveExpectationChain.new(*args)
|
59
|
+
else
|
60
|
+
RSpec::Mocks::AnyInstance::ExpectationChain.new(*args)
|
61
|
+
end
|
63
62
|
end
|
64
63
|
|
65
64
|
end
|
data/lib/better_receive.rb
CHANGED
@@ -2,8 +2,8 @@ require "better_receive/version"
|
|
2
2
|
require "better_receive/mock"
|
3
3
|
|
4
4
|
module BetterReceive
|
5
|
-
def better_receive(
|
6
|
-
Mock.new(self).responds_to_and_receives(
|
5
|
+
def better_receive(*args)
|
6
|
+
Mock.new(self).responds_to_and_receives(*args)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BetterReceive do
|
4
|
+
class Foo
|
5
|
+
def bar(baz = nil)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#responds_to_and_receives" do
|
10
|
+
let(:foo) { Foo.new }
|
11
|
+
let(:br_mock) { BetterReceive::Mock.new(foo) }
|
12
|
+
|
13
|
+
it "determines whether an object responds to a method" do
|
14
|
+
foo.should_receive(:respond_to?).with(:bar).and_return(true)
|
15
|
+
|
16
|
+
br_mock.responds_to_and_receives :bar
|
17
|
+
|
18
|
+
foo.bar
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises an error if it the method is not defined" do
|
22
|
+
expect {
|
23
|
+
br_mock.responds_to_and_receives :bar_baz
|
24
|
+
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
|
25
|
+
error.message.should =~ /to respond to :bar_baz/
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when mocking" do
|
30
|
+
let(:mock_proxy) { double(RSpec::Mocks::Proxy) }
|
31
|
+
|
32
|
+
it "creates a mock proxy and adds an expectation to it" do
|
33
|
+
foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
|
34
|
+
mock_proxy.should_receive(:add_message_expectation)
|
35
|
+
|
36
|
+
br_mock.responds_to_and_receives :bar
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns an rspec message expectation(responds to additional matchers ('with', 'once'...))" do
|
40
|
+
foo.better_receive(:bar).should be_a RSpec::Mocks::MessageExpectation
|
41
|
+
|
42
|
+
foo.bar
|
43
|
+
|
44
|
+
br_mock.responds_to_and_receives(:bar).with('wibble')
|
45
|
+
|
46
|
+
foo.bar('wibble')
|
47
|
+
end
|
48
|
+
|
49
|
+
context "and passing arguments" do
|
50
|
+
let(:block_param) { Proc.new {} }
|
51
|
+
let(:options) { {passed: true} }
|
52
|
+
|
53
|
+
it "passes all arguments through to the mock_proxy" do
|
54
|
+
foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
|
55
|
+
mock_proxy.should_receive(:add_message_expectation) do |*args, &block|
|
56
|
+
args[1].should == :bar
|
57
|
+
args[2].should == options
|
58
|
+
block.should == block_param
|
59
|
+
end
|
60
|
+
|
61
|
+
br_mock.responds_to_and_receives(:bar, passed: true, &block_param)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "on .any_instance" do
|
66
|
+
let(:br_mock) { BetterReceive::Mock.new(Foo.any_instance) }
|
67
|
+
|
68
|
+
context "when the method is defined" do
|
69
|
+
context "and the method is called" do
|
70
|
+
it 'does not raise an error' do
|
71
|
+
expect {
|
72
|
+
br_mock.responds_to_and_receives(:bar)
|
73
|
+
foo.bar
|
74
|
+
}.to_not raise_error
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'and the method is not called' do
|
79
|
+
it 'does raise an error' do
|
80
|
+
expect {
|
81
|
+
br_mock.responds_to_and_receives(:bar)
|
82
|
+
RSpec::Mocks::space.verify_all
|
83
|
+
}.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
|
84
|
+
error.message.should == "Exactly one instance should have received the following message(s) but didn't: bar"
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when the method is not defined' do
|
91
|
+
it 'raises an error' do
|
92
|
+
expect {
|
93
|
+
br_mock.responds_to_and_receives(:baz)
|
94
|
+
}.to raise_error { |error|
|
95
|
+
error.message.should == "Expected instances of Foo to respond to :baz"
|
96
|
+
}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -2,98 +2,25 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe BetterReceive do
|
4
4
|
class Foo
|
5
|
-
def bar
|
6
|
-
end
|
5
|
+
def bar; end
|
7
6
|
end
|
8
7
|
|
9
8
|
describe "#better_receive" do
|
10
9
|
let(:foo) { Foo.new }
|
10
|
+
let(:br_instance) { double(BetterReceive::Mock).as_null_object }
|
11
11
|
|
12
|
-
it "
|
13
|
-
|
12
|
+
it "passes the object being mocked into a new BetterReceive::Mock instance" do
|
13
|
+
BetterReceive::Mock.should_receive(:new).with(foo).and_return(br_instance)
|
14
14
|
|
15
15
|
foo.better_receive(:bar)
|
16
|
-
|
17
|
-
foo.bar
|
18
|
-
end
|
19
|
-
|
20
|
-
it "raises an error if it the method is not defined" do
|
21
|
-
expect {
|
22
|
-
foo.better_receive(:bar_baz)
|
23
|
-
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
|
24
|
-
error.message.should =~ /to respond to :bar_baz/
|
25
|
-
}
|
26
16
|
end
|
27
17
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
it "creates a mock proxy and adds an expectation to it" do
|
32
|
-
foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
|
33
|
-
mock_proxy.should_receive(:add_message_expectation)
|
34
|
-
|
35
|
-
foo.better_receive(:bar)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "returns an rspec message expectation(responds to additional matchers ('with', 'once'...))" do
|
39
|
-
foo.better_receive(:bar).should be_a RSpec::Mocks::MessageExpectation
|
40
|
-
|
41
|
-
foo.bar
|
18
|
+
it "checks that the object responds to the method and that the method is called" do
|
19
|
+
BetterReceive::Mock.stub(:new).with(foo).and_return(br_instance)
|
42
20
|
|
43
|
-
|
21
|
+
br_instance.should_receive(:responds_to_and_receives).with(:bar)
|
44
22
|
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
context "and passing arguments" do
|
49
|
-
let(:block_param) { Proc.new {} }
|
50
|
-
let(:options) { {passed: true} }
|
51
|
-
|
52
|
-
it "passes all arguments through to the mock_proxy" do
|
53
|
-
foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
|
54
|
-
mock_proxy.should_receive(:add_message_expectation) do |*args, &block|
|
55
|
-
args[1].should == :bar
|
56
|
-
args[2].should == options
|
57
|
-
block.should == block_param
|
58
|
-
end
|
59
|
-
|
60
|
-
foo.better_receive(:bar, passed: true, &block_param)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
context "on .any_instance" do
|
65
|
-
context "when the method is defined" do
|
66
|
-
context "and the method is called" do
|
67
|
-
it 'does not raise an error' do
|
68
|
-
expect {
|
69
|
-
Foo.any_instance.better_receive(:bar)
|
70
|
-
foo.bar
|
71
|
-
}.to_not raise_error
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'and the method is not called' do
|
76
|
-
it 'does raise an error' do
|
77
|
-
expect {
|
78
|
-
Foo.any_instance.better_receive(:bar)
|
79
|
-
RSpec::Mocks::space.verify_all
|
80
|
-
}.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
|
81
|
-
error.message.should == "Exactly one instance should have received the following message(s) but didn't: bar"
|
82
|
-
}
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'when the method is not defined' do
|
88
|
-
it 'raises an error' do
|
89
|
-
expect {
|
90
|
-
Foo.any_instance.better_receive(:baz)
|
91
|
-
}.to raise_error { |error|
|
92
|
-
error.message.should == "Expected instances of Foo to respond to :baz"
|
93
|
-
}
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
23
|
+
foo.better_receive(:bar)
|
97
24
|
end
|
98
25
|
end
|
99
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_receive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- lib/better_receive.rb
|
80
80
|
- lib/better_receive/mock.rb
|
81
81
|
- lib/better_receive/version.rb
|
82
|
+
- spec/lib/better_receive/mock_spec.rb
|
82
83
|
- spec/lib/better_receive_spec.rb
|
83
84
|
- spec/spec_helper.rb
|
84
85
|
homepage: http://github.com/se3000/better_receive
|
@@ -104,7 +105,8 @@ rubyforge_project:
|
|
104
105
|
rubygems_version: 1.8.23
|
105
106
|
signing_key:
|
106
107
|
specification_version: 3
|
107
|
-
summary: A
|
108
|
+
summary: A more assertive mock.
|
108
109
|
test_files:
|
110
|
+
- spec/lib/better_receive/mock_spec.rb
|
109
111
|
- spec/lib/better_receive_spec.rb
|
110
112
|
- spec/spec_helper.rb
|