better_receive 0.3.0 → 0.4.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 CHANGED
@@ -1,6 +1,7 @@
1
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/se3000/better_receive)
1
2
  # BetterReceive
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
+ Test drive new functionality and prevent bugs by asserting objects respond to methods when mocking/stubbing.
4
5
 
5
6
  ## Installation
6
7
 
@@ -10,17 +11,22 @@ BetterReceive helps test drive new functionality and prevent bugs by asserting t
10
11
 
11
12
 
12
13
  ```ruby
14
+
13
15
  class Foo; end
14
16
  foo = Foo.new
15
17
 
16
18
  foo.better_receive(:bar)
19
+ # or
20
+ foo.better_stub(bar: 1, baz: 2)
21
+ # or
22
+ Foo.any_instance.better_receive(:bar).with(:wibble)
23
+
17
24
  ```
18
- or
19
- ```ruby
20
- Foo.any_instance.better_receive(:bar)
21
- ```
22
25
 
23
- Either situation will raise an error because instances of Foo do not respond to :bar.
26
+ Any of these situation will raise an error because instances of Foo do not respond to :bar.
27
+
28
+ After the initial extra assertion, they continue to act like regular RSpec mocks/stubs.
29
+
24
30
 
25
31
  ## Contributing
26
32
 
@@ -32,7 +38,6 @@ Either situation will raise an error because instances of Foo do not respond to
32
38
 
33
39
  ## To Do
34
40
 
35
- * #better_stub
36
41
  * support arrity checks with #responds_to
37
42
  * support options other than Ruby 1.9.2+ and RSpec
38
43
 
@@ -1,9 +1,15 @@
1
1
  require "better_receive/version"
2
+ require "better_receive/base"
2
3
  require "better_receive/mock"
4
+ require "better_receive/stub"
3
5
 
4
6
  module BetterReceive
5
- def better_receive(*args)
6
- Mock.new(self).responds_to_and_receives(*args)
7
+ def better_receive(*args, &block)
8
+ Mock.new(self).assert_with(*args, &block)
9
+ end
10
+
11
+ def better_stub(*args, &block)
12
+ Stub.new(self).assert_with(*args, &block)
7
13
  end
8
14
  end
9
15
 
@@ -0,0 +1,47 @@
1
+ module BetterReceive
2
+ class Base
3
+
4
+ def initialize(subject)
5
+ @subject = subject
6
+ end
7
+
8
+
9
+ private
10
+
11
+ attr_reader :subject
12
+
13
+ def subject_is_any_instance?
14
+ subject.is_a?(RSpec::Mocks::AnyInstance::Recorder)
15
+ end
16
+
17
+ def respond_to(selector)
18
+ RSpec::Matchers::BuiltIn::RespondTo.new(selector)
19
+ end
20
+
21
+ def subject_mock_proxy
22
+ @mock_proxy ||= subject.send(:__mock_proxy)
23
+ end
24
+
25
+ def any_instance_better_expect(selector, options, &block)
26
+ any_instance_should_respond_to selector
27
+ any_instance_add_expectation selector, &block
28
+ end
29
+
30
+ def any_instance_should_respond_to(selector)
31
+ klass = subject.instance_variable_get(:@klass)
32
+ unless klass.method_defined?(selector)
33
+ raise "Expected instances of #{klass.name} to respond to :#{selector}"
34
+ end
35
+ end
36
+
37
+ def any_instance_add_expectation(selector, &block)
38
+ RSpec::Mocks::space.add(subject)
39
+
40
+ subject.instance_variable_set(:@expectation_set, true)
41
+ subject.send(:observe!, selector)
42
+
43
+ subject.message_chains.add(selector, expectation_chain(selector, &block))
44
+ end
45
+
46
+ end
47
+ end
@@ -1,13 +1,9 @@
1
1
  module BetterReceive
2
- class Mock
2
+ class Mock < Base
3
3
 
4
- def initialize(subject)
5
- @subject = subject
6
- end
7
-
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)
4
+ def assert_with(selector, options={}, &block)
5
+ if subject_is_any_instance?
6
+ any_instance_better_expect(selector, options, &block)
11
7
  else
12
8
  subject.should respond_to selector
13
9
  mock_subject_method(selector, options, &block)
@@ -17,42 +13,11 @@ module BetterReceive
17
13
 
18
14
  private
19
15
 
20
- attr_reader :subject
21
-
22
- def respond_to(selector)
23
- RSpec::Matchers::BuiltIn::RespondTo.new(selector)
24
- end
25
-
26
16
  def mock_subject_method(selector, options, &block)
27
17
  location = options[:expected_from] || caller(1)[2]
28
18
  subject_mock_proxy.add_message_expectation(location, selector, options, &block)
29
19
  end
30
20
 
31
- def subject_mock_proxy
32
- @mock_proxy ||= subject.send(:__mock_proxy)
33
- end
34
-
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}"
44
- end
45
- end
46
-
47
- def any_instance_should_receive(selector, &block)
48
- RSpec::Mocks::space.add(subject)
49
-
50
- subject.instance_variable_set(:@expectation_set, true)
51
- subject.send(:observe!, selector)
52
-
53
- subject.message_chains.add(selector, expectation_chain(selector, &block))
54
- end
55
-
56
21
  def expectation_chain(*args)
57
22
  if defined?(RSpec::Mocks::AnyInstance::PositiveExpectationChain)
58
23
  RSpec::Mocks::AnyInstance::PositiveExpectationChain.new(*args)
@@ -0,0 +1,36 @@
1
+ module BetterReceive
2
+ class Stub < Base
3
+
4
+ def assert_with(selector_or_hash, options={}, &block)
5
+ if selector_or_hash.is_a?(Hash)
6
+ selector_or_hash.each do |selector, value|
7
+ better_stub_method(selector, options, &block).and_return(value)
8
+ end
9
+ else
10
+ better_stub_method(selector_or_hash, options, &block)
11
+ end
12
+ end
13
+
14
+
15
+ private
16
+
17
+ def better_stub_method(selector, options, &block)
18
+ if subject_is_any_instance?
19
+ any_instance_better_expect(selector, options, &block)
20
+ else
21
+ subject.should respond_to selector
22
+ stub_subject_method(selector, options, &block)
23
+ end
24
+ end
25
+
26
+ def stub_subject_method(selector, options, &block)
27
+ location = options[:expected_from] || caller(1)[2]
28
+ subject_mock_proxy.add_stub(location, selector, options, &block)
29
+ end
30
+
31
+ def expectation_chain(*args)
32
+ RSpec::Mocks::AnyInstance::StubChain.new(*args)
33
+ end
34
+
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module BetterReceive
2
- BETTER_VERSION = "0.3.0"
2
+ BETTER_VERSION = "0.4.0"
3
3
  end
@@ -1,26 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe BetterReceive do
3
+ describe BetterReceive::Mock do
4
4
  class Foo
5
5
  def bar(baz = nil)
6
6
  end
7
7
  end
8
8
 
9
- describe "#responds_to_and_receives" do
9
+ describe "#assert_with" do
10
10
  let(:foo) { Foo.new }
11
11
  let(:br_mock) { BetterReceive::Mock.new(foo) }
12
12
 
13
13
  it "determines whether an object responds to a method" do
14
14
  foo.should_receive(:respond_to?).with(:bar).and_return(true)
15
15
 
16
- br_mock.responds_to_and_receives :bar
16
+ br_mock.assert_with :bar
17
17
 
18
18
  foo.bar
19
19
  end
20
20
 
21
- it "raises an error if it the method is not defined" do
21
+ it "raises an error if the method is not defined" do
22
22
  expect {
23
- br_mock.responds_to_and_receives :bar_baz
23
+ br_mock.assert_with :bar_baz
24
24
  }.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
25
25
  error.message.should =~ /to respond to :bar_baz/
26
26
  }
@@ -33,7 +33,7 @@ describe BetterReceive do
33
33
  foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
34
34
  mock_proxy.should_receive(:add_message_expectation)
35
35
 
36
- br_mock.responds_to_and_receives :bar
36
+ br_mock.assert_with :bar
37
37
  end
38
38
 
39
39
  it "returns an rspec message expectation(responds to additional matchers ('with', 'once'...))" do
@@ -41,7 +41,7 @@ describe BetterReceive do
41
41
 
42
42
  foo.bar
43
43
 
44
- br_mock.responds_to_and_receives(:bar).with('wibble')
44
+ br_mock.assert_with(:bar).with('wibble')
45
45
 
46
46
  foo.bar('wibble')
47
47
  end
@@ -58,7 +58,7 @@ describe BetterReceive do
58
58
  block.should == block_param
59
59
  end
60
60
 
61
- br_mock.responds_to_and_receives(:bar, passed: true, &block_param)
61
+ br_mock.assert_with(:bar, passed: true, &block_param)
62
62
  end
63
63
  end
64
64
 
@@ -69,7 +69,7 @@ describe BetterReceive do
69
69
  context "and the method is called" do
70
70
  it 'does not raise an error' do
71
71
  expect {
72
- br_mock.responds_to_and_receives(:bar)
72
+ br_mock.assert_with(:bar)
73
73
  foo.bar
74
74
  }.to_not raise_error
75
75
  end
@@ -78,7 +78,7 @@ describe BetterReceive do
78
78
  context 'and the method is not called' do
79
79
  it 'does raise an error' do
80
80
  expect {
81
- br_mock.responds_to_and_receives(:bar)
81
+ br_mock.assert_with(:bar)
82
82
  RSpec::Mocks::space.verify_all
83
83
  }.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
84
84
  error.message.should == "Exactly one instance should have received the following message(s) but didn't: bar"
@@ -90,7 +90,7 @@ describe BetterReceive do
90
90
  context 'when the method is not defined' do
91
91
  it 'raises an error' do
92
92
  expect {
93
- br_mock.responds_to_and_receives(:baz)
93
+ br_mock.assert_with(:baz)
94
94
  }.to raise_error { |error|
95
95
  error.message.should == "Expected instances of Foo to respond to :baz"
96
96
  }
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ describe BetterReceive::Stub do
4
+ class Foo
5
+ def bar(baz = nil)
6
+ end
7
+ end
8
+
9
+ describe "#assert_with" do
10
+ let(:foo) { Foo.new }
11
+ let(:br_stub) { BetterReceive::Stub.new(foo) }
12
+
13
+ context "when passed a single selector" do
14
+ context "when checking responds to" do
15
+ it "determines whether an object responds to a method" do
16
+ foo.should_receive(:respond_to?).with(:bar).and_return(true)
17
+
18
+ br_stub.assert_with :bar
19
+
20
+ foo.bar
21
+ end
22
+
23
+ it "raises an error if the method is not defined" do
24
+ expect {
25
+ br_stub.assert_with :bar_baz
26
+ }.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
27
+ error.message.should =~ /to respond to :bar_baz/
28
+ }
29
+ end
30
+ end
31
+
32
+ context "when stubbing" do
33
+ let(:mock_proxy) { double(RSpec::Mocks::Proxy).as_null_object }
34
+ let(:block_param) { Proc.new {} }
35
+ let(:options) { {passed: true} }
36
+
37
+ it "creates a mock proxy and adds an expectation to it" do
38
+ foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
39
+ mock_proxy.should_receive(:add_stub)
40
+
41
+ br_stub.assert_with :bar
42
+ end
43
+
44
+ it "returns an rspec message expectation(responds to additional matchers ('with', 'once'...))" do
45
+ br_stub.assert_with(:bar).should be_a RSpec::Mocks::MessageExpectation
46
+
47
+
48
+ br_stub.assert_with(:bar).with('wibble')
49
+ end
50
+
51
+ it "passes all arguments through to the mock_proxy" do
52
+ foo.should_receive(:send).with(:__mock_proxy).and_return(mock_proxy)
53
+ mock_proxy.should_receive(:add_stub) do |*args, &block|
54
+ args[1].should == :bar
55
+ args[2].should == options
56
+ block.should == block_param
57
+ end
58
+
59
+ br_stub.assert_with(:bar, passed: true, &block_param)
60
+ end
61
+
62
+ it "returns the value passed in the block" do
63
+ br_stub.assert_with(:bar) { :baz }
64
+
65
+ foo.bar.should == :baz
66
+ end
67
+ end
68
+ end
69
+
70
+ context "when passed a hash" do
71
+ class Foo
72
+ def extra; end
73
+ end
74
+
75
+ context "and checking responds to" do
76
+ it "determines whether an object responds to a method" do
77
+ params = {bar: '1', extra: '2'}
78
+
79
+ foo.should_receive(:respond_to?).with(:bar).and_return(true)
80
+ foo.should_receive(:respond_to?).with(:extra).and_return(true)
81
+
82
+ br_stub.assert_with params
83
+ end
84
+
85
+ it "raises an error if the method is not defined" do
86
+ params = {bar: '1', baz: '2'}
87
+
88
+ expect{
89
+ br_stub.assert_with params
90
+ }.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
91
+ error.message.should =~ /to respond to :baz/
92
+ }
93
+ end
94
+ end
95
+
96
+ context "and stubbing" do
97
+ it 'stubs out each method' do
98
+ params = {bar: '1', extra: '2'}
99
+ br_stub.assert_with params
100
+
101
+ foo.bar.should == '1'
102
+ foo.extra.should == '2'
103
+ end
104
+ end
105
+ end
106
+
107
+ context "on .any_instance" do
108
+ let(:br_stub) { BetterReceive::Stub.new(Foo.any_instance) }
109
+
110
+ context "when the method is defined" do
111
+ it 'stubs the method out' do
112
+ br_stub.assert_with(:bar).and_return(:whatever)
113
+
114
+ foo.bar.should == :whatever
115
+ end
116
+ end
117
+
118
+ context 'when the method is not defined' do
119
+ it 'raises an error' do
120
+ expect {
121
+ br_stub.assert_with(:baz)
122
+ }.to raise_error { |error|
123
+ error.message.should == "Expected instances of Foo to respond to :baz"
124
+ }
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -18,9 +18,62 @@ describe BetterReceive do
18
18
  it "checks that the object responds to the method and that the method is called" do
19
19
  BetterReceive::Mock.stub(:new).with(foo).and_return(br_instance)
20
20
 
21
- br_instance.should_receive(:responds_to_and_receives).with(:bar)
21
+ br_instance.should_receive(:assert_with).with(:bar)
22
22
 
23
23
  foo.better_receive(:bar)
24
24
  end
25
+
26
+ it "returns an RSpec expectation object" do
27
+ foo.better_receive(:bar).should be_a RSpec::Mocks::MessageExpectation
28
+
29
+ foo.bar
30
+
31
+
32
+ foo.better_receive(:bar).with('wibble')
33
+
34
+ foo.bar('wibble')
35
+ end
36
+
37
+ it "returns the value of the block passed in" do
38
+ foo.better_receive(:bar) { :baz }
39
+
40
+ foo.bar.should == :baz
41
+ end
42
+ end
43
+
44
+ describe "#better_stub" do
45
+ let(:foo) { Foo.new }
46
+ let(:br_instance) { double(BetterReceive::Stub).as_null_object }
47
+
48
+ it "passes the object being stubbed into a new BetterReceive::Stub instance" do
49
+ BetterReceive::Stub.should_receive(:new).with(foo).and_return(br_instance)
50
+
51
+ foo.better_stub(:bar)
52
+ end
53
+
54
+ it "checks that the object responds to the method and that the method is called" do
55
+ BetterReceive::Stub.stub(:new).with(foo).and_return(br_instance)
56
+
57
+ br_instance.should_receive(:assert_with).with(:bar)
58
+
59
+ foo.better_stub(:bar)
60
+ end
61
+
62
+ it "returns an RSpec expectation object" do
63
+ foo.better_stub(:bar).should be_a RSpec::Mocks::MessageExpectation
64
+
65
+ foo.bar
66
+
67
+
68
+ foo.better_stub(:bar).with('wibble')
69
+
70
+ foo.bar('wibble')
71
+ end
72
+
73
+ it "returns the value of the block passed in" do
74
+ foo.better_stub(:bar) { :baz }
75
+
76
+ foo.bar.should == :baz
77
+ end
25
78
  end
26
79
  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.3.0
4
+ version: 0.4.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-27 00:00:00.000000000 Z
13
+ date: 2013-01-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -77,9 +77,12 @@ files:
77
77
  - Rakefile
78
78
  - better_receive.gemspec
79
79
  - lib/better_receive.rb
80
+ - lib/better_receive/base.rb
80
81
  - lib/better_receive/mock.rb
82
+ - lib/better_receive/stub.rb
81
83
  - lib/better_receive/version.rb
82
84
  - spec/lib/better_receive/mock_spec.rb
85
+ - spec/lib/better_receive/stub_spec.rb
83
86
  - spec/lib/better_receive_spec.rb
84
87
  - spec/spec_helper.rb
85
88
  homepage: http://github.com/se3000/better_receive
@@ -108,5 +111,6 @@ specification_version: 3
108
111
  summary: A more assertive mock.
109
112
  test_files:
110
113
  - spec/lib/better_receive/mock_spec.rb
114
+ - spec/lib/better_receive/stub_spec.rb
111
115
  - spec/lib/better_receive_spec.rb
112
116
  - spec/spec_helper.rb