verified_double 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d5009534213dea01c257cd3ae51146bc3b851074
4
+ data.tar.gz: 2fdb0e7501414b89f06ea63c886736b615a47604
5
+ SHA512:
6
+ metadata.gz: 415c67746889f7cb267f8f792ec33c6dffd106b361c6bf72ecfca91a7f9625e2f8813c3ef0c9d5314ba1500dbf393f12bab591ae651641c0017ad662b867673f
7
+ data.tar.gz: 56740f7d553a0ee07f42dce4f6b7bc2844228046d5640c207421585a8f0effe8401f717b20358241822c20c7b3b781cb2a7484e79a919ccdeceaac621687d9af
@@ -0,0 +1,67 @@
1
+ # Refer to https://github.com/bbatsov/rubocop/blob/master/config/default.yml
2
+ # for the default rubocop configuration.
3
+
4
+ AllCops:
5
+ Excludes:
6
+ - db/schema.rb
7
+ - db/fixtures/development/cooking_methods.rb
8
+ - db/fixtures/development/food_categories.rb
9
+ - db/fixtures/development/kitcategories.rb
10
+ - db/fixtures/development/kitsubcats.rb
11
+ - db/fixtures/development/main_ingredients.rb
12
+ - db/fixtures/development/recipe_categories.rb
13
+ - db/fixtures/development/special_occasions.rb
14
+ - db/fixtures/development/states.rb
15
+ Includes:
16
+ - '*.rake'
17
+ - Capfile
18
+ - Gemfile
19
+ - Guardfile
20
+
21
+ AlignHash:
22
+ Enabled: false
23
+
24
+ AlignParameters:
25
+ Enabled: false
26
+
27
+ AsciiComments:
28
+ Enabled: false
29
+
30
+ ClassLength:
31
+ Enabled: false
32
+
33
+ Documentation:
34
+ Enabled: false
35
+
36
+ EmptyLines:
37
+ Enabled: false
38
+
39
+ Encoding:
40
+ Enabled: false
41
+
42
+ FavorUnlessOverNegatedIf:
43
+ Enabled: false
44
+
45
+ IfUnlessModifier:
46
+ Enabled: false
47
+
48
+ LineLength:
49
+ Max: 89
50
+
51
+ MethodLength:
52
+ Max: 30
53
+
54
+ MethodCalledOnDoEndBlock:
55
+ Enabled: true
56
+
57
+ RedundantReturn:
58
+ AllowMultipleReturnValues: true
59
+
60
+ RedundantSelf:
61
+ Enabled: false
62
+
63
+ SignalException:
64
+ Enabled: false
65
+
66
+ StringLiterals:
67
+ Enabled: false
@@ -1,3 +1,11 @@
1
+ 0.5.0 - 2013-12-24
2
+ ------------------
3
+
4
+ * [#27] Implement describe "contract" feature.
5
+
6
+ * [#22] Add VerifiedDouble.any_instance_of(klass). Warning: only works with
7
+ should_receive. Doesn't work with expect/allow syntax.
8
+
1
9
  0.4.3 - 2013-10-22
2
10
  ------------------
3
11
 
@@ -0,0 +1,11 @@
1
+ guard :rspec do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
7
+ guard 'cucumber' do
8
+ watch(%r{^features/.+\.feature$})
9
+ watch(%r{^features/support/.+$}) { 'features' }
10
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
11
+ end
data/README.md CHANGED
@@ -2,58 +2,169 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
4
4
 
5
- VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if the doubled classes respond to the methods, the gem looks for tests confirming if those mocks are valid.
5
+ VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if a doubled class responds to the methods, the gem looks for tests confirming the signatures of the mocks.
6
6
 
7
- For example, let's say I mocked the created_at method of a model like this:
7
+ For example, if I mock the created_at method of a model like this:
8
8
 
9
- item = VerifiedDouble.of_instance(Item)
10
- expect(item).to receive(:created_at).and_return(Time.now)
9
+ ```ruby
10
+ item = VerifiedDouble.of_instance(Item)
11
+ expect(item).to receive(:created_at).and_return(Time.now)
12
+ ```
11
13
 
12
- When running the tests, the gem looks for a "contract test" tagged with the method's signature. This test should ensure that calling #created_at on Item will return a Time object.
14
+ When I run the tests, the gem will look for a "contract test" tagged with the method's signature. This test should ensure that calling `#created_at` on Item will return a Time object.
13
15
 
14
- it "tests something", verifies_contract: 'Item#created_at()=>Time' do
16
+ ```ruby
17
+ describe Item do
18
+ describe '#created_at()=>Time', verifies_contract: true do
19
+ it "tests something" do
15
20
  #...
16
21
  end
22
+ end
23
+ end
24
+ ```
17
25
 
18
26
  If this test does not exist, the gem will complain that the mock is not verified.
19
27
 
20
28
  I got the idea from http://www.infoq.com/presentations/integration-tests-scam, an old (2009) talk that still has some fresh insights on dealing with API changes in your mocked tests.
21
29
 
22
- Usage
23
- -----
30
+ ## Setup
24
31
 
25
32
  Require `verified_double/rspec_configuration` in your spec_helper.rb to integrate VerifiedDouble with rspec. If you want verified_double to be run only as needed, create a separate verified_spec_helper.rb:
26
33
 
27
- # spec/verified_spec_helper.rb
28
- require 'spec_helper'
29
- require 'verified_double/rspec_configuration'
34
+ ```
35
+ # spec/verified_spec_helper.rb
36
+ require 'spec_helper'
37
+ require 'verified_double/rspec_configuration'
38
+ ```
30
39
 
31
40
  And require it when running rspec:
32
41
 
33
42
  rspec -r ./spec/verified_spec_helper.rb
34
43
 
35
- You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
44
+ ## Usage
36
45
 
37
- Actively tested against
38
- -----------------------
46
+ Let's look again at the example above:
39
47
 
40
- * Ruby 1.9.3
41
- * RSpec 2.14
48
+ ```ruby
49
+ item = VerifiedDouble.of_instance(Item)
50
+ expect(item).to receive(:created_at).and_return(Time.now)
51
+ ```
52
+
53
+ When you run this test, you'll see a warning saying that there's no test verifying the mock `Item#created_at()=>Time`:
54
+
55
+ ```
56
+ The following mocks are not verified:
57
+
58
+ 1. Item#created_at()=>Time
59
+ ...
60
+
61
+ ```
62
+
63
+ You can then tag the test for `Item#created_at()=>Time` with the method signature:
64
+
65
+ ```ruby
66
+ describe Item do
67
+ describe '#created_at()=>Time', verifies_contract: true do
68
+ it "tests something" do
69
+ #...
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ Take note that:
76
+
77
+ 1. The described class must be a class, not a string.
78
+ 2. The described method must start with `#` if its an instance method and `.` if it's a class method.
79
+ 3. You need to add the add the `verifies_contract: true` tag to the test.
80
+
81
+ If your testing style doesn't follow these conventions, you can tag the test with the whole method signature:
82
+
83
+ ```ruby
84
+ describe 'Item' do
85
+ it "has a creation timestamp", verifies_contract: `Item#created_at()=>Time` do
86
+ #...
87
+ end
88
+ end
89
+ ```
90
+
91
+ Since VerifiedDouble relies on tags to link mocks and contracts together, you'll
92
+ need to run the tests containing the contracts along with tests with the mocks in
93
+ order to clear the VerifiedDouble warnings.
94
+
95
+ ## Booleans
96
+
97
+ Since Ruby doesn't have Boolean class covering both `TrueClass` and `FalseClass`,
98
+ VerifiedDouble supplies its own `VerifiedDouble::Boolean` class. Thus if your method
99
+ accepts or returns a boolean value, you'll see `VerifiedDouble::Boolean` in its
100
+ method signature e.g. `Student.late?()=>VerifiedDouble::Boolean`.
42
101
 
102
+ ## Helpers
43
103
 
44
- Alternatives
45
- ------------
104
+ Most of the time, you'll be mocking accessor methods. VerifiedDouble provides some
105
+ helpers to make them easy to verify.
46
106
 
47
- [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
107
+ For reader methods, there's the `verify_reader_contract` matcher. The matcher checks
108
+ if the method will return an object matching the class specified by the contract:
48
109
 
49
- Caveats
50
- -------
110
+ ```ruby
111
+ class Collaborator
112
+ attr_reader :value
113
+
114
+ def initialize(value)
115
+ @value = value
116
+ end
117
+ end
118
+
119
+ class SomeValue
120
+ end
121
+
122
+ describe Collaborator do
123
+ subject { described_class.new(SomeValue.new) }
124
+ it { should verify_reader_contract('Collaborator#value=>SomeValue') }
125
+ end
126
+ ```
127
+
128
+ For accessor methods, there's the `verify_accessor_contract` matcher. The matcher
129
+ instantiates the return class and tries to pass and retrieve the value
130
+ to the method:
131
+
132
+ ```ruby
133
+ class Collaborator
134
+ attr_accessor :value
135
+ end
136
+
137
+ describe Collaborator do
138
+ it { should verify_accessor_contract('Collaborator#value=>SomeValue') }
139
+ end
140
+ ```
141
+
142
+ ## Any Instance mocks
143
+
144
+ Aside for instance and class doubles, VerifiedDouble also supports `any_instance` mocks:
145
+
146
+ ```
147
+ VerifiedDouble.any_instance_of(Collaborator)
148
+ .should_receive(:some_method).with(input).and_return(output)
149
+ ```
150
+
151
+ You'll need to use should_receive for `any_instance` mocks. I still have to figure
152
+ out how to make it work with RSpec's `expect_any_instance_of` syntax :p
153
+
154
+ ## Complete documentation
155
+
156
+ You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
157
+
158
+ ## Actively tested against
159
+
160
+ * Ruby 2.0
161
+ * RSpec 2.14
51
162
 
52
- * With 0.3.0, doubles created with VerifiedDouble.of_instance() and VerifiedDouble.of_class() are now VerifiedDouble-extended RSpec doubles. As a result, they should function like regular RSpec doubles. However, VerifiedDouble still doesn't have support for [RSpec mock argument matchers](https://github.com/rspec/rspec-mocks#argument-matchers). Please post an issue at http://github.com/gsmendoza/verified_double if you need support for any particular rspec-mock API.
163
+ ## Alternatives
53
164
 
54
- * The [method documentation](http://rubydoc.info/gems/verified_double) is pretty empty at this point :p I'm planning to use yard-spec to document the methods but that gem doesn't support rspec context blocks. I'll try to work on that soon.
165
+ [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem I know to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
55
166
 
56
- Special thanks
57
- --------------
167
+ ## Special thanks
58
168
 
59
- To [Thomas Sinclair](https://twitter.com/anathematic) of [Inner Core Designs](http://icdesign.com.au) for initially sponsoring this gem.
169
+ * [Inner Core Designs](http://icdesign.com.au)
170
+ * [Love With Food](https://lovewithfood.com)
@@ -1,3 +1,11 @@
1
+ 0.5.0 - 2013-12-24
2
+ ------------------
3
+
4
+ * [#27] Implement describe "contract" feature.
5
+
6
+ * [#22] Add VerifiedDouble.any_instance_of(klass). Warning: only works with
7
+ should_receive. Doesn't work with expect/allow syntax.
8
+
1
9
  0.4.3 - 2013-10-22
2
10
  ------------------
3
11
 
@@ -1,4 +1,4 @@
1
- Feature: 05. Accessor method contracts
1
+ Feature: 40. Accessor method contracts
2
2
  As a developer
3
3
  I want it to easy to verify contracts for accessor methods
4
4
 
@@ -0,0 +1,95 @@
1
+ Feature: 60. Any instance
2
+
3
+ Background:
4
+ Given the following classes:
5
+ """
6
+ class ObjectUnderTest
7
+ def do_something(collaborator, input)
8
+ collaborator.some_method(input)
9
+ end
10
+
11
+ def self.do_something(input)
12
+ Collaborator.some_method(input)
13
+ end
14
+ end
15
+
16
+ class Collaborator
17
+ def self.some_method(input)
18
+ end
19
+
20
+ def some_method(input)
21
+ end
22
+ end
23
+
24
+ class SomeInput
25
+ end
26
+
27
+ class SomeOutput
28
+ end
29
+ """
30
+
31
+ And the test suite is configured to use VerifiedDouble:
32
+ """
33
+ require 'verified_double'
34
+ require 'verified_double/rspec_configuration'
35
+ require 'main'
36
+ """
37
+
38
+ Scenario: Verify any instance of a class
39
+
40
+ Given a test that uses VerifiedDouble to mock any instance of the class:
41
+ """
42
+ require 'spec_helper'
43
+ describe ObjectUnderTest do
44
+ let(:input) { SomeInput.new }
45
+ let(:output) { SomeOutput.new }
46
+
47
+ it "tests something" do
48
+ VerifiedDouble.any_instance_of(Collaborator)
49
+ .should_receive(:some_method).with(input).and_return(output)
50
+
51
+ ObjectUnderTest.new.do_something(Collaborator.new, input)
52
+ end
53
+ end
54
+ """
55
+
56
+ And the test suite has a contract test for the mock:
57
+ """
58
+ require 'spec_helper'
59
+
60
+ describe 'Collaborator' do
61
+ it "tests something",
62
+ verifies_contract: 'Collaborator#some_method(SomeInput)=>SomeOutput' do
63
+ # do nothing
64
+ end
65
+ end
66
+ """
67
+
68
+ When I run the test suite
69
+ Then I should not see any output saying the mock is unverified
70
+
71
+ Scenario: Unverified any_instance mock
72
+ Given a test that uses VerifiedDouble to mock any instance of the class:
73
+ """
74
+ require 'spec_helper'
75
+ describe ObjectUnderTest do
76
+ let(:input) { SomeInput.new }
77
+ let(:output) { SomeOutput.new }
78
+
79
+ it "tests something" do
80
+ VerifiedDouble.any_instance_of(Collaborator)
81
+ .should_receive(:some_method).with(input).and_return(output)
82
+
83
+ ObjectUnderTest.new.do_something(Collaborator.new, input)
84
+ end
85
+ end
86
+ """
87
+
88
+ And the test suite does not have a contract test for the mock
89
+ When I run the test suite
90
+ Then I should be informed that the mock is unverified:
91
+ """
92
+ The following mocks are not verified:
93
+
94
+ 1. Collaborator#some_method(SomeInput)=>SomeOutput
95
+ """
@@ -1,4 +1,4 @@
1
- Feature: 04. Customizing arguments and return values
1
+ Feature: 50. Customizing arguments and return values
2
2
  As a developer
3
3
  I want the ability to make contract arguments and return values more or less specific
4
4
 
@@ -0,0 +1,67 @@
1
+ Feature: 30. Describe contract
2
+ Scenario: Specify contact in describe string
3
+ Given the following classes:
4
+
5
+ """
6
+ class ObjectUnderTest
7
+ def do_something(collaborator, input)
8
+ collaborator.some_method(input)
9
+ end
10
+ end
11
+
12
+ class Collaborator
13
+ def some_method(input)
14
+ end
15
+ end
16
+
17
+ class SomeInput
18
+ end
19
+
20
+ class SomeOutput
21
+ end
22
+ """
23
+
24
+ And the test suite is configured to use VerifiedDouble:
25
+
26
+ """
27
+ require 'verified_double'
28
+ require 'verified_double/rspec_configuration'
29
+ require 'main'
30
+ """
31
+
32
+ And a test that uses VerifiedDouble to mock an object:
33
+
34
+ """
35
+ require 'spec_helper'
36
+ describe ObjectUnderTest do
37
+ let(:input) { SomeInput.new }
38
+ let(:output) { SomeOutput.new }
39
+ let(:collaborator) { VerifiedDouble.of_instance('Collaborator') }
40
+
41
+ it "tests something" do
42
+ expect(collaborator)
43
+ .to receive(:some_method).with(input).and_return(output)
44
+
45
+ ObjectUnderTest.new.do_something(collaborator, input)
46
+ end
47
+ end
48
+ """
49
+
50
+ And the test suite has a contract test for the mock:
51
+
52
+ """
53
+ require 'spec_helper'
54
+
55
+ describe Collaborator do
56
+ context 'with some context' do
57
+ describe '#some_method(SomeInput)=>SomeOutput', verifies_contract: true do
58
+ it "tests something" do
59
+ # do nothing
60
+ end
61
+ end
62
+ end
63
+ end
64
+ """
65
+
66
+ When I run the test suite
67
+ Then I should not see any output saying the mock is unverified
@@ -2,58 +2,169 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/gsmendoza/verified_double.png)](https://travis-ci.org/gsmendoza/verified_double)
4
4
 
5
- VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if the doubled classes respond to the methods, the gem looks for tests confirming if those mocks are valid.
5
+ VerifiedDouble is a gem for verifying rspec mocks. The gem works similar to [rspec-fire](https://github.com/xaviershay/rspec-fire). However, instead of checking if a doubled class responds to the methods, the gem looks for tests confirming the signatures of the mocks.
6
6
 
7
- For example, let's say I mocked the created_at method of a model like this:
7
+ For example, if I mock the created_at method of a model like this:
8
8
 
9
- item = VerifiedDouble.of_instance(Item)
10
- expect(item).to receive(:created_at).and_return(Time.now)
9
+ ```ruby
10
+ item = VerifiedDouble.of_instance(Item)
11
+ expect(item).to receive(:created_at).and_return(Time.now)
12
+ ```
11
13
 
12
- When running the tests, the gem looks for a "contract test" tagged with the method's signature. This test should ensure that calling #created_at on Item will return a Time object.
14
+ When I run the tests, the gem will look for a "contract test" tagged with the method's signature. This test should ensure that calling `#created_at` on Item will return a Time object.
13
15
 
14
- it "tests something", verifies_contract: 'Item#created_at()=>Time' do
16
+ ```ruby
17
+ describe Item do
18
+ describe '#created_at()=>Time', verifies_contract: true do
19
+ it "tests something" do
15
20
  #...
16
21
  end
22
+ end
23
+ end
24
+ ```
17
25
 
18
26
  If this test does not exist, the gem will complain that the mock is not verified.
19
27
 
20
28
  I got the idea from http://www.infoq.com/presentations/integration-tests-scam, an old (2009) talk that still has some fresh insights on dealing with API changes in your mocked tests.
21
29
 
22
- Usage
23
- -----
30
+ ## Setup
24
31
 
25
32
  Require `verified_double/rspec_configuration` in your spec_helper.rb to integrate VerifiedDouble with rspec. If you want verified_double to be run only as needed, create a separate verified_spec_helper.rb:
26
33
 
27
- # spec/verified_spec_helper.rb
28
- require 'spec_helper'
29
- require 'verified_double/rspec_configuration'
34
+ ```
35
+ # spec/verified_spec_helper.rb
36
+ require 'spec_helper'
37
+ require 'verified_double/rspec_configuration'
38
+ ```
30
39
 
31
40
  And require it when running rspec:
32
41
 
33
42
  rspec -r ./spec/verified_spec_helper.rb
34
43
 
35
- You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
44
+ ## Usage
36
45
 
37
- Actively tested against
38
- -----------------------
46
+ Let's look again at the example above:
39
47
 
40
- * Ruby 1.9.3
41
- * RSpec 2.14
48
+ ```ruby
49
+ item = VerifiedDouble.of_instance(Item)
50
+ expect(item).to receive(:created_at).and_return(Time.now)
51
+ ```
52
+
53
+ When you run this test, you'll see a warning saying that there's no test verifying the mock `Item#created_at()=>Time`:
54
+
55
+ ```
56
+ The following mocks are not verified:
57
+
58
+ 1. Item#created_at()=>Time
59
+ ...
60
+
61
+ ```
62
+
63
+ You can then tag the test for `Item#created_at()=>Time` with the method signature:
64
+
65
+ ```ruby
66
+ describe Item do
67
+ describe '#created_at()=>Time', verifies_contract: true do
68
+ it "tests something" do
69
+ #...
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ Take note that:
76
+
77
+ 1. The described class must be a class, not a string.
78
+ 2. The described method must start with `#` if its an instance method and `.` if it's a class method.
79
+ 3. You need to add the add the `verifies_contract: true` tag to the test.
80
+
81
+ If your testing style doesn't follow these conventions, you can tag the test with the whole method signature:
82
+
83
+ ```ruby
84
+ describe 'Item' do
85
+ it "has a creation timestamp", verifies_contract: `Item#created_at()=>Time` do
86
+ #...
87
+ end
88
+ end
89
+ ```
90
+
91
+ Since VerifiedDouble relies on tags to link mocks and contracts together, you'll
92
+ need to run the tests containing the contracts along with tests with the mocks in
93
+ order to clear the VerifiedDouble warnings.
94
+
95
+ ## Booleans
96
+
97
+ Since Ruby doesn't have Boolean class covering both `TrueClass` and `FalseClass`,
98
+ VerifiedDouble supplies its own `VerifiedDouble::Boolean` class. Thus if your method
99
+ accepts or returns a boolean value, you'll see `VerifiedDouble::Boolean` in its
100
+ method signature e.g. `Student.late?()=>VerifiedDouble::Boolean`.
42
101
 
102
+ ## Helpers
43
103
 
44
- Alternatives
45
- ------------
104
+ Most of the time, you'll be mocking accessor methods. VerifiedDouble provides some
105
+ helpers to make them easy to verify.
46
106
 
47
- [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
107
+ For reader methods, there's the `verify_reader_contract` matcher. The matcher checks
108
+ if the method will return an object matching the class specified by the contract:
48
109
 
49
- Caveats
50
- -------
110
+ ```ruby
111
+ class Collaborator
112
+ attr_reader :value
113
+
114
+ def initialize(value)
115
+ @value = value
116
+ end
117
+ end
118
+
119
+ class SomeValue
120
+ end
121
+
122
+ describe Collaborator do
123
+ subject { described_class.new(SomeValue.new) }
124
+ it { should verify_reader_contract('Collaborator#value=>SomeValue') }
125
+ end
126
+ ```
127
+
128
+ For accessor methods, there's the `verify_accessor_contract` matcher. The matcher
129
+ instantiates the return class and tries to pass and retrieve the value
130
+ to the method:
131
+
132
+ ```ruby
133
+ class Collaborator
134
+ attr_accessor :value
135
+ end
136
+
137
+ describe Collaborator do
138
+ it { should verify_accessor_contract('Collaborator#value=>SomeValue') }
139
+ end
140
+ ```
141
+
142
+ ## Any Instance mocks
143
+
144
+ Aside for instance and class doubles, VerifiedDouble also supports `any_instance` mocks:
145
+
146
+ ```
147
+ VerifiedDouble.any_instance_of(Collaborator)
148
+ .should_receive(:some_method).with(input).and_return(output)
149
+ ```
150
+
151
+ You'll need to use should_receive for `any_instance` mocks. I still have to figure
152
+ out how to make it work with RSpec's `expect_any_instance_of` syntax :p
153
+
154
+ ## Complete documentation
155
+
156
+ You can learn more about using the gem at https://www.relishapp.com/gsmendoza/verified-double.
157
+
158
+ ## Actively tested against
159
+
160
+ * Ruby 2.0
161
+ * RSpec 2.14
51
162
 
52
- * With 0.3.0, doubles created with VerifiedDouble.of_instance() and VerifiedDouble.of_class() are now VerifiedDouble-extended RSpec doubles. As a result, they should function like regular RSpec doubles. However, VerifiedDouble still doesn't have support for [RSpec mock argument matchers](https://github.com/rspec/rspec-mocks#argument-matchers). Please post an issue at http://github.com/gsmendoza/verified_double if you need support for any particular rspec-mock API.
163
+ ## Alternatives
53
164
 
54
- * The [method documentation](http://rubydoc.info/gems/verified_double) is pretty empty at this point :p I'm planning to use yard-spec to document the methods but that gem doesn't support rspec context blocks. I'll try to work on that soon.
165
+ [Bogus](https://www.relishapp.com/bogus/bogus/v/0-0-3/docs/) is the first gem I know to implement contract tests. It doesn't rely on rspec tags to verify contracts, so it's probably a lot smarter than VerifiedDouble :) However, I wasn't able to try it out on my own projects because of its own rr-like mock adapter. But do check it out!
55
166
 
56
- Special thanks
57
- --------------
167
+ ## Special thanks
58
168
 
59
- To [Thomas Sinclair](https://twitter.com/anathematic) of [Inner Core Designs](http://icdesign.com.au) for initially sponsoring this gem.
169
+ * [Inner Core Designs](http://icdesign.com.au)
170
+ * [Love With Food](https://lovewithfood.com)
@@ -1,4 +1,4 @@
1
- Feature: 03. Rspec Mock compatibility
1
+ Feature: 70. Rspec Mock compatibility
2
2
  As a developer
3
3
  I want VerifiedDouble to work with Rspec Mock API
4
4
 
@@ -6,6 +6,10 @@ Given /^a test that uses VerifiedDouble to mock an object:$/ do |string|
6
6
  write_file 'spec/main_spec.rb', string
7
7
  end
8
8
 
9
+ Given(/^a test that uses VerifiedDouble to mock any instance of the class:$/) do |string|
10
+ write_file 'spec/main_spec.rb', string
11
+ end
12
+
9
13
  Given /^a test that uses VerifiedDouble to stub an object:$/ do |string|
10
14
  write_file 'spec/main_spec.rb', string
11
15
  end
@@ -1,4 +1,4 @@
1
- Feature: 01. Verified mocks
1
+ Feature: 10. Verified mocks
2
2
  As a developer
3
3
  I want to be informed if the mocks I use are verified by contract tests
4
4
 
@@ -206,3 +206,4 @@ Feature: 01. Verified mocks
206
206
 
207
207
  1. Collaborator.some_method(SomeInput)=>SomeOutput
208
208
  """
209
+
@@ -1,4 +1,4 @@
1
- Feature: 02. Verified stubs
1
+ Feature: 20. Verified stubs
2
2
  As a developer
3
3
  I want to be informed if the stubs I use are verified by contract tests
4
4
 
@@ -3,6 +3,7 @@ require 'rspec/mocks'
3
3
 
4
4
  require 'verified_double/boolean'
5
5
  require 'verified_double/can_record_interactions'
6
+ require 'verified_double/example_metadata'
6
7
  require 'verified_double/is_a_class_double'
7
8
  require 'verified_double/is_an_instance_double'
8
9
  require 'verified_double/matchers'
@@ -23,6 +24,12 @@ require 'verified_double/stack_frame'
23
24
  module VerifiedDouble
24
25
  extend RSpec::Mocks::ExampleMethods
25
26
 
27
+ def self.any_instance_of(klass)
28
+ d = klass.any_instance
29
+ d.extend(VerifiedDouble::IsAnInstanceDouble)
30
+ VerifiedDouble.record(d)
31
+ end
32
+
26
33
  def self.of_class(class_value, options = {})
27
34
  options[:transfer_nested_constants] = true if options[:transfer_nested_constants].nil?
28
35
  d = stub_const(class_value.to_s, Class.new, options)
@@ -0,0 +1,31 @@
1
+ module VerifiedDouble
2
+ class ExampleMetadata < Struct.new(:metadata)
3
+ def described_class
4
+ if description.is_a?(Module)
5
+ description
6
+ elsif description.is_a?(String)
7
+ ExampleMetadata.new(metadata[:example_group]).described_class
8
+ else
9
+ raise
10
+ end
11
+ end
12
+
13
+ def description
14
+ metadata[:description_args][0]
15
+ end
16
+
17
+ def method_signature_string
18
+ if description =~ /^[\.\#]/
19
+ description
20
+ elsif description.nil?
21
+ raise
22
+ else
23
+ ExampleMetadata.new(metadata[:example_group]).method_signature_string
24
+ end
25
+ end
26
+
27
+ def verified_signature
28
+ "#{described_class}#{method_signature_string}"
29
+ end
30
+ end
31
+ end
@@ -49,13 +49,23 @@ module VerifiedDouble
49
49
  end
50
50
 
51
51
  def set_verified_signatures_from_tags(nested_example_group)
52
- @verified_signatures_from_tags = nested_example_group
52
+ examples = nested_example_group
53
53
  .class
54
54
  .descendant_filtered_examples
55
- .map{|example| example.metadata[:verifies_contract] }
55
+
56
+ verified_signatures = examples.map do |example|
57
+ if example.metadata[:verifies_contract] == true
58
+ ExampleMetadata.new(example.metadata).verified_signature
59
+ else
60
+ example.metadata[:verifies_contract]
61
+ end
62
+ end
63
+
64
+ @verified_signatures_from_tags = verified_signatures
56
65
  .compact
57
66
  .uniq
58
67
  .map{|method_signature_string| ParseMethodSignature.new(method_signature_string).execute }
68
+
59
69
  self
60
70
  end
61
71
  end
@@ -11,7 +11,14 @@ module VerifiedDouble
11
11
 
12
12
  def expect(*args)
13
13
  if args[0].respond_to?(:can_record_interactions?)
14
- VerifiedDouble.registry.current_double = args[0]
14
+ if args[0].is_a?(RSpec::Mocks::AnyInstance::Recorder)
15
+ raise "VerifiedDouble.any_instance_of doesn't support yet Rspec's " \
16
+ "expect/allow syntax. Please use should_receive."
17
+ else
18
+ VerifiedDouble.registry.current_double = args[0]
19
+ end
20
+
21
+
15
22
  else
16
23
  VerifiedDouble.registry.current_double = nil
17
24
  end
@@ -15,13 +15,29 @@ module VerifiedDouble
15
15
 
16
16
 
17
17
  def class_name
18
- class_double? ? internal.name : internal.instance_variable_get('@name').to_s
18
+ if class_double?
19
+ internal.name
20
+ elsif instance_double?
21
+ internal.instance_variable_get('@name').to_s
22
+ elsif any_instance_double?
23
+ internal.instance_variable_get('@klass').to_s
24
+ else
25
+ raise
26
+ end
27
+ end
28
+
29
+ def any_instance_double?
30
+ !! internal.instance_variable_get('@klass')
19
31
  end
20
32
 
21
33
  def class_double?
22
34
  internal.respond_to?(:verified_class_double?)
23
35
  end
24
36
 
37
+ def instance_double?
38
+ !! internal.instance_variable_get('@name')
39
+ end
40
+
25
41
  def method_operator
26
42
  class_double? ? '.' : '#'
27
43
  end
@@ -1,3 +1,3 @@
1
1
  module VerifiedDouble
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe VerifiedDouble::ExampleMetadata do
4
+ let(:klass) { Object }
5
+ let(:method_signature_string) { '#to_s()=>String' }
6
+ let(:metadata) do
7
+ {
8
+ description_args: ['is a string representing the object'],
9
+ example_group: {
10
+ description_args: [method_signature_string],
11
+
12
+ example_group: {
13
+ description_args: ['with some context'],
14
+
15
+ example_group: {
16
+ description_args: [klass]
17
+ }
18
+ }
19
+ }
20
+ }
21
+ end
22
+
23
+ subject { described_class.new(metadata) }
24
+
25
+ describe '#verified_signature' do
26
+ it 'is the class_name and method_signature_string' do
27
+ expect(subject.verified_signature).to eq("#{klass}#{method_signature_string}")
28
+ end
29
+ end
30
+
31
+ describe '#described_class' do
32
+ it "is the described class of the metadata's test source" do
33
+ expect(subject.described_class).to eq(klass)
34
+ end
35
+
36
+ context "where the described class is a string" do
37
+ let(:metadata) do
38
+ {
39
+ example_group: {
40
+ description_args: [klass.to_s]
41
+ }
42
+ }
43
+ end
44
+
45
+ it "should raise an error" do
46
+ expect(-> { subject.described_class }).to raise_error
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#method_signature_string' do
52
+ it "is the signature of the method being tested" do
53
+ expect(subject.method_signature_string).to eq(method_signature_string)
54
+ end
55
+
56
+ context "where there is no description arg that looks like a method signature" do
57
+ let(:metadata) do
58
+ {
59
+ example_group: {
60
+ description_args: [klass.to_s]
61
+ }
62
+ }
63
+ end
64
+
65
+ it "should raise an error" do
66
+ expect(-> { subject.method_signature_string }).to raise_error
67
+ end
68
+ end
69
+ end
70
+ end
71
+
@@ -15,6 +15,15 @@ describe VerifiedDouble::RSpecMocksSyntaxOverrides do
15
15
  end
16
16
  end
17
17
 
18
+ context "where the double arg is an RSpec::Mocks::AnyInstance::Recorder" do
19
+ let(:a_double) { VerifiedDouble.of_instance('Object') }
20
+
21
+ it "should tell the user to use should_receive instead" do
22
+ expect(lambda { expect(VerifiedDouble.any_instance_of(Object)) })
23
+ .to raise_error
24
+ end
25
+ end
26
+
18
27
  context "where the double arg does not record VerifiedDouble interactions" do
19
28
  let(:a_double) { double('Object') }
20
29
 
@@ -76,4 +85,4 @@ describe VerifiedDouble::RSpecMocksSyntaxOverrides do
76
85
  end
77
86
  end
78
87
  end
79
- end
88
+ end
@@ -22,5 +22,9 @@ Gem::Specification.new do |gem|
22
22
 
23
23
  gem.add_development_dependency "aruba"
24
24
  gem.add_development_dependency "cucumber"
25
+ gem.add_development_dependency "guard"
26
+ gem.add_development_dependency "guard-cucumber"
27
+ gem.add_development_dependency "guard-rspec"
25
28
  gem.add_development_dependency "pry"
29
+ gem.add_development_dependency "rubocop"
26
30
  end
metadata CHANGED
@@ -1,96 +1,141 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verified_double
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.4.3
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - George Mendoza
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-10-22 00:00:00.000000000 Z
11
+ date: 2013-12-24 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- type: :runtime
14
+ name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
20
+ type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
- none: false
25
23
  requirements:
26
- - - ! '>='
24
+ - - '>='
27
25
  - !ruby/object:Gem::Version
28
26
  version: '0'
29
- name: activesupport
30
27
  - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
31
34
  type: :runtime
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: aruba
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
- - - ! '>='
45
+ - - '>='
36
46
  - !ruby/object:Gem::Version
37
47
  version: '0'
48
+ type: :development
38
49
  prerelease: false
39
50
  version_requirements: !ruby/object:Gem::Requirement
40
- none: false
41
51
  requirements:
42
- - - ! '>='
52
+ - - '>='
43
53
  - !ruby/object:Gem::Version
44
54
  version: '0'
45
- name: rspec
46
55
  - !ruby/object:Gem::Dependency
56
+ name: cucumber
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
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: guard
48
71
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
72
  requirements:
51
- - - ! '>='
73
+ - - '>='
52
74
  - !ruby/object:Gem::Version
53
75
  version: '0'
76
+ type: :development
54
77
  prerelease: false
55
78
  version_requirements: !ruby/object:Gem::Requirement
56
- none: false
57
79
  requirements:
58
- - - ! '>='
80
+ - - '>='
59
81
  - !ruby/object:Gem::Version
60
82
  version: '0'
61
- name: aruba
62
83
  - !ruby/object:Gem::Dependency
84
+ name: guard-cucumber
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
63
90
  type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
64
99
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
100
  requirements:
67
- - - ! '>='
101
+ - - '>='
68
102
  - !ruby/object:Gem::Version
69
103
  version: '0'
104
+ type: :development
70
105
  prerelease: false
71
106
  version_requirements: !ruby/object:Gem::Requirement
72
- none: false
73
107
  requirements:
74
- - - ! '>='
108
+ - - '>='
75
109
  - !ruby/object:Gem::Version
76
110
  version: '0'
77
- name: cucumber
78
111
  - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
79
118
  type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
80
127
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
128
  requirements:
83
- - - ! '>='
129
+ - - '>='
84
130
  - !ruby/object:Gem::Version
85
131
  version: '0'
132
+ type: :development
86
133
  prerelease: false
87
134
  version_requirements: !ruby/object:Gem::Requirement
88
- none: false
89
135
  requirements:
90
- - - ! '>='
136
+ - - '>='
91
137
  - !ruby/object:Gem::Version
92
138
  version: '0'
93
- name: pry
94
139
  description: Contract tests for rspec
95
140
  email:
96
141
  - gsmendoza@gmail.com
@@ -99,15 +144,19 @@ extensions: []
99
144
  extra_rdoc_files: []
100
145
  files:
101
146
  - .gitignore
147
+ - .rubocop.yml
102
148
  - .travis.yml
103
149
  - CHANGELOG.markdown
104
150
  - Gemfile
151
+ - Guardfile
105
152
  - LICENSE.txt
106
153
  - README.md
107
154
  - Rakefile
108
155
  - features/CHANGELOG.markdown
109
156
  - features/accessor_method_contracts.feature
157
+ - features/any_instance.feature
110
158
  - features/customizing_arguments_and_return_values.feature
159
+ - features/describe_contract.feature
111
160
  - features/readme.md
112
161
  - features/rspec_mock_compatibility.feature
113
162
  - features/step_definitions/verified_double_steps.rb
@@ -117,6 +166,7 @@ files:
117
166
  - lib/verified_double.rb
118
167
  - lib/verified_double/boolean.rb
119
168
  - lib/verified_double/can_record_interactions.rb
169
+ - lib/verified_double/example_metadata.rb
120
170
  - lib/verified_double/is_a_class_double.rb
121
171
  - lib/verified_double/is_an_instance_double.rb
122
172
  - lib/verified_double/matchers.rb
@@ -138,6 +188,7 @@ files:
138
188
  - spec/spec_helper.rb
139
189
  - spec/support/shared_examples.rb
140
190
  - spec/verified_double/can_record_interactions_spec.rb
191
+ - spec/verified_double/example_metadata_spec.rb
141
192
  - spec/verified_double/matchers_spec.rb
142
193
  - spec/verified_double/method_signature/boolean_value_spec.rb
143
194
  - spec/verified_double/method_signature/class_value_spec.rb
@@ -156,33 +207,34 @@ files:
156
207
  - verified_double.gemspec
157
208
  homepage: https://www.relishapp.com/gsmendoza/verified-double
158
209
  licenses: []
210
+ metadata: {}
159
211
  post_install_message:
160
212
  rdoc_options: []
161
213
  require_paths:
162
214
  - lib
163
215
  required_ruby_version: !ruby/object:Gem::Requirement
164
- none: false
165
216
  requirements:
166
- - - ! '>='
217
+ - - '>='
167
218
  - !ruby/object:Gem::Version
168
219
  version: '0'
169
220
  required_rubygems_version: !ruby/object:Gem::Requirement
170
- none: false
171
221
  requirements:
172
- - - ! '>='
222
+ - - '>='
173
223
  - !ruby/object:Gem::Version
174
224
  version: '0'
175
225
  requirements: []
176
226
  rubyforge_project:
177
- rubygems_version: 1.8.24
227
+ rubygems_version: 2.1.11
178
228
  signing_key:
179
- specification_version: 3
229
+ specification_version: 4
180
230
  summary: VerifiedDouble would record any mock made in the test suite. It would then
181
231
  verify if the mock is valid by checking if there is a test against it.
182
232
  test_files:
183
233
  - features/CHANGELOG.markdown
184
234
  - features/accessor_method_contracts.feature
235
+ - features/any_instance.feature
185
236
  - features/customizing_arguments_and_return_values.feature
237
+ - features/describe_contract.feature
186
238
  - features/readme.md
187
239
  - features/rspec_mock_compatibility.feature
188
240
  - features/step_definitions/verified_double_steps.rb
@@ -192,6 +244,7 @@ test_files:
192
244
  - spec/spec_helper.rb
193
245
  - spec/support/shared_examples.rb
194
246
  - spec/verified_double/can_record_interactions_spec.rb
247
+ - spec/verified_double/example_metadata_spec.rb
195
248
  - spec/verified_double/matchers_spec.rb
196
249
  - spec/verified_double/method_signature/boolean_value_spec.rb
197
250
  - spec/verified_double/method_signature/class_value_spec.rb
@@ -207,4 +260,3 @@ test_files:
207
260
  - spec/verified_double/simple_double_spec.rb
208
261
  - spec/verified_double/stack_frame_spec.rb
209
262
  - spec/verified_double_spec.rb
210
- has_rdoc: