better_receive 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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