surrogate 0.5.0 → 0.5.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.
data/Readme.md CHANGED
@@ -5,6 +5,14 @@ Handrolling mocks is the best, but involves more overhead than necessary, and us
5
5
  error messages. Surrogate addresses this by endowing your objects with common things that most mocks need.
6
6
  Currently it is only integrated with RSpec.
7
7
 
8
+ This codebase should be considered highly volatile until 1.0 release. The outer interface should be
9
+ fairly stable, with each 0.a.b version having backwards compatibility for any changes to b (ie
10
+ only refactorings and new features), and possible interface changes (though probably minimal)
11
+ for changes to a. Depending on the internals of the code (anything not shown in the readme) is
12
+ discouraged at this time. If you do want to do this (e.g. to make an interface for test/unit)
13
+ let me know, and I'll inform you / fork your gem and help update it, for any breaking changes
14
+ that I introduce.
15
+
8
16
 
9
17
  Features
10
18
  ========
@@ -250,6 +258,27 @@ user.should have_been_initialized_with 12
250
258
  ```
251
259
 
252
260
 
261
+ Predicates
262
+ ----------
263
+
264
+ Query qith `have_been_asked_if`, all the same chainable methods from above apply.
265
+
266
+ ```ruby
267
+ class MockUser
268
+ Surrogate.endow self
269
+ define(:admin?) { false }
270
+ end
271
+
272
+ user = MockUser.new
273
+ user.should_not be_admin
274
+ user.will_have_admin? true
275
+ user.should be_admin
276
+ user.should have_been_asked_if(:admin?).times(2)
277
+ ```
278
+
279
+
280
+ class MockUser
281
+
253
282
  Substitutability
254
283
  ----------------
255
284
 
@@ -394,11 +423,9 @@ TODO
394
423
  ----
395
424
 
396
425
  * Add proper failure messages for block invocations
397
- * Add `was told_to` syntax
398
- * Add support for predicates
399
426
  * Add a better explanation for motivations
400
427
  * Figure out whether I'm supposed to be using clone or dup for the object -.^ (looks like there may also be an `initialize_copy` method I can take advantage of instead of crazy stupid shit I'm doing now)
401
- * don't blow up when delegating to the Object#initialize with args
428
+ * don't blow up when delegating to the Object#initialize with args (do I still want this, or do I want to force arity matching (and maybe even variable name matching)?)
402
429
  * config: rspec_mocks loaded, whether unprepared blocks should raise or just return nil
403
430
  * extract surrogate/rspec into its own gem
404
431
  * support subset-substitutabilty not being able to touch real methods (e.g. #respond_to?)
@@ -5,6 +5,14 @@ class Surrogate
5
5
  # please refactor me! ...may not be possible :(
6
6
  # Can we move all method definitions into this class?
7
7
  class Endower
8
+ def self.add_hook(&block)
9
+ hooks << block
10
+ end
11
+
12
+ def self.hooks
13
+ @hooks ||= []
14
+ end
15
+
8
16
  def self.endow(klass, &block)
9
17
  new(klass, &block).endow
10
18
  end
@@ -28,6 +36,7 @@ class Surrogate
28
36
  enable_defining_methods klass
29
37
  record_initialization_for_instances_of klass
30
38
  remember_invocations_for_instances_of klass
39
+ invoke_hooks klass
31
40
  end
32
41
 
33
42
  def endow_singleton_class
@@ -36,9 +45,14 @@ class Surrogate
36
45
  singleton.module_eval &block if block
37
46
  klass.instance_variable_set :@hatchling, Hatchling.new(klass, hatchery)
38
47
  remember_invocations_for_instances_of singleton
48
+ invoke_hooks singleton
39
49
  klass
40
50
  end
41
51
 
52
+ def invoke_hooks(klass)
53
+ self.class.hooks.each { |hook| hook.call klass }
54
+ end
55
+
42
56
  # yeesh :( pretty sure there isn't a better way to do this
43
57
  def record_initialization_for_instances_of(klass)
44
58
  def klass.method_added(meth)
@@ -0,0 +1,71 @@
1
+ require 'surrogate/rspec/invocation_matcher'
2
+
3
+ class Surrogate
4
+ module RSpec
5
+ class HaveBeenAskedIf < InvocationMatcher
6
+ class FailureMessageShouldDefault < AbstractFailureMessage
7
+ def get_message
8
+ "was never asked if #{ method_name }"
9
+ end
10
+ end
11
+
12
+ class FailureMessageShouldWith < AbstractFailureMessage
13
+ def get_message
14
+ message = "should have been asked if #{ method_name } with #{ inspect_arguments expected_invocation }, but "
15
+ if times_invoked.zero?
16
+ message << "was never asked"
17
+ else
18
+ inspected_invocations = invocations.map { |invocation| inspect_arguments invocation }
19
+ message << "got #{inspected_invocations.join ', '}"
20
+ end
21
+ end
22
+ end
23
+
24
+ class FailureMessageShouldTimes < AbstractFailureMessage
25
+ def get_message
26
+ "should have been asked if #{ method_name } #{ times_msg expected_times_invoked }, but was asked #{ times_msg times_invoked }"
27
+ end
28
+ end
29
+
30
+ class FailureMessageWithTimes < AbstractFailureMessage
31
+ def get_message
32
+ message = "should have been asked if #{ method_name } #{ times_msg expected_times_invoked } with #{ inspect_arguments expected_invocation }, but "
33
+ if times_invoked.zero?
34
+ message << "was never asked"
35
+ else
36
+ message << "was asked #{times_msg times_invoked}"
37
+ end
38
+ end
39
+ end
40
+
41
+ class FailureMessageShouldNotDefault < AbstractFailureMessage
42
+ def get_message
43
+ "shouldn't have been asked if #{ method_name }, but was asked #{ times_msg times_invoked }"
44
+ end
45
+ end
46
+
47
+ class FailureMessageShouldNotWith < AbstractFailureMessage
48
+ def get_message
49
+ message = "should not have been asked if #{ method_name } with #{ inspect_arguments expected_invocation }"
50
+ end
51
+ end
52
+
53
+ class FailureMessageShouldNotTimes < AbstractFailureMessage
54
+ def get_message
55
+ "shouldn't have been asked if #{ method_name } #{ times_msg expected_times_invoked }, but was"
56
+ end
57
+ end
58
+
59
+ class FailureMessageShouldNotWithTimes < AbstractFailureMessage
60
+ def get_message
61
+ message = "should not have been asked if #{ method_name } #{ times_msg expected_times_invoked } with #{ inspect_arguments expected_invocation }, "
62
+ if times_invoked.zero?
63
+ message << "was never asked"
64
+ else
65
+ message << "was asked #{times_msg times_invoked}"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,8 @@
1
1
  # Maybe I should be my own gem?
2
2
 
3
+ require 'rspec/core'
4
+ require 'surrogate'
5
+
3
6
  class Surrogate
4
7
  module RSpec
5
8
  class << self
@@ -19,25 +22,50 @@ class Surrogate
19
22
  end
20
23
 
21
24
  module Matchers
22
- def have_been_told_to(expected)
23
- HaveBeenToldTo.new expected
25
+ def have_been_told_to(method_name)
26
+ HaveBeenToldTo.new method_name
27
+ end
28
+
29
+ def told_to(method_name)
30
+ HaveBeenToldTo.new method_name
31
+ end
32
+
33
+ def have_been_asked_if(method_name)
34
+ HaveBeenAskedIf.new method_name
35
+ end
36
+
37
+ def asked_if(method_name)
38
+ HaveBeenAskedIf.new method_name
39
+ end
40
+
41
+ def have_been_asked_for_its(method_name)
42
+ HaveBeenAskedForIts.new method_name
24
43
  end
25
44
 
26
- def have_been_asked_for_its(expected)
27
- HaveBeenAskedForIts.new expected
45
+ def asked_for(method_name)
46
+ HaveBeenAskedForIts.new method_name
28
47
  end
29
48
 
30
49
  def have_been_initialized_with(*initialization_args, &block)
31
50
  HaveBeenInitializedWith.new *initialization_args, &block
32
51
  end
52
+
53
+ def initialized_with(*initialization_args, &block)
54
+ HaveBeenInitializedWith.new *initialization_args, &block
55
+ end
56
+ end
57
+ end
58
+
59
+ Endower.add_hook do |klass|
60
+ klass.class_eval do
61
+ alias was should
62
+ alias was_not should_not
33
63
  end
34
64
  end
35
65
  end
36
66
 
37
- require 'rspec/core'
38
- require 'surrogate'
39
67
  require 'surrogate/rspec/substitute_for'
40
-
68
+ require 'surrogate/rspec/have_been_asked_if'
41
69
  require 'surrogate/rspec/have_been_asked_for_its'
42
70
  require 'surrogate/rspec/have_been_initialized_with'
43
71
  require 'surrogate/rspec/have_been_told_to'
@@ -1,3 +1,3 @@
1
1
  class Surrogate
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'RSpec matchers', 'have_been_initialized_with' do
3
+ describe 'should/should_not have_been_initialized_with' do
4
4
  let(:mocked_class) { Surrogate.endow Class.new }
5
5
  before { mocked_class.module_eval { def initialize(*) end } } # b/c 1.9.3 will have arity issues otherwise
6
6
 
@@ -27,3 +27,31 @@ describe 'RSpec matchers', 'have_been_initialized_with' do
27
27
  failure_message_for { mocked_class.new("1").should_not have_been_told_to(:initialize).with('1') }
28
28
  end
29
29
  end
30
+
31
+ describe 'was/was_not initialized_with' do
32
+ let(:mocked_class) { Surrogate.endow Class.new }
33
+ before { mocked_class.module_eval { def initialize(*) end } } # b/c 1.9.3 will have arity issues otherwise
34
+
35
+ it 'is the same as have_been_told_to(:initialize).with(...)' do
36
+ mocked_class.new.was initialized_with no_args
37
+ mocked_class.new.was_not initialized_with 1
38
+ mocked_class.new(1).was initialized_with 1
39
+ mocked_class.new(1, '2').was initialized_with 1, '2'
40
+ end
41
+
42
+ def failure_message_for
43
+ yield
44
+ rescue RSpec::Expectations::ExpectationNotMetError
45
+ $!.message
46
+ end
47
+
48
+ example 'failure message for should' do
49
+ failure_message_for { mocked_class.new("1").was initialized_with 2 }.should ==
50
+ failure_message_for { mocked_class.new("1").was told_to(:initialize).with(2) }
51
+ end
52
+
53
+ example 'failure message for should not' do
54
+ failure_message_for { mocked_class.new("1").was_not initialized_with('1') }.should ==
55
+ failure_message_for { mocked_class.new("1").was_not told_to(:initialize).with('1') }
56
+ end
57
+ end
@@ -1,32 +1,48 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'RSpec matchers', 'have_been_asked_for_its' do
3
+ shared_examples_for 'a noun matcher' do
4
4
  let(:mocked_class) { Surrogate.endow Class.new }
5
5
  let(:instance) { mocked_class.new }
6
6
 
7
+ def did_ask(argument, modifiers={})
8
+ assert!(positive_assertion, argument, modifiers)
9
+ end
10
+
11
+ def did_not_ask(argument, modifiers={})
12
+ assert!(negative_assertion, argument, modifiers)
13
+ end
14
+
15
+ def assert!(assertion, argument, modifiers)
16
+ matcher = send(matcher_name, argument)
17
+ matcher.send(:with, *modifiers[:with]) if modifiers.has_key? :with
18
+ matcher.send(:times, modifiers[:times]) if modifiers.has_key? :times
19
+ instance.send(assertion, matcher)
20
+ end
21
+
22
+
7
23
  describe 'default use case' do
8
24
  before { mocked_class.define :name, default: 'Ayaan' }
9
25
 
10
26
  example 'passes if has been invoked at least once' do
11
- instance.should_not have_been_asked_for_its :name
27
+ did_not_ask :name
12
28
  instance.name
13
- instance.should have_been_asked_for_its :name
29
+ did_ask :name
14
30
  instance.name
15
- instance.should have_been_asked_for_its :name
31
+ did_ask :name
16
32
  end
17
33
 
18
34
  example 'failure message for should' do
19
- expect { instance.should have_been_asked_for_its :name }.to \
35
+ expect { did_ask :name }.to \
20
36
  raise_error(RSpec::Expectations::ExpectationNotMetError, /was never asked for its name/)
21
37
  end
22
38
 
23
39
  example 'failure message for should not' do
24
40
  instance.name
25
- expect { instance.should_not have_been_asked_for_its :name }.to \
41
+ expect { did_not_ask :name }.to \
26
42
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its name, but was asked 1 time/)
27
43
 
28
44
  instance.name
29
- expect { instance.should_not have_been_asked_for_its :name }.to \
45
+ expect { did_not_ask :name }.to \
30
46
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its name, but was asked 2 times/)
31
47
  end
32
48
  end
@@ -36,41 +52,41 @@ describe 'RSpec matchers', 'have_been_asked_for_its' do
36
52
  before { mocked_class.define :size, default: nil }
37
53
 
38
54
  example 'default use case' do
39
- instance.should_not have_been_asked_for_its(:size).with(1, 2, 3)
55
+ did_not_ask :size, with: [1, 2, 3]
40
56
  instance.size 1, 2
41
- instance.should_not have_been_asked_for_its(:size).with(1, 2, 3)
57
+ did_not_ask :size, with: [1, 2, 3]
42
58
  instance.size 1, 2, 3
43
- instance.should have_been_asked_for_its(:size).with(1, 2, 3)
59
+ did_ask :size, with: [1, 2, 3]
44
60
  end
45
61
 
46
62
  example 'failure message for should' do
47
- expect { instance.should have_been_asked_for_its(:size).with(1, '2') }.to \
63
+ expect { did_ask :size, with: [1, '2'] }.to \
48
64
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its size with `1, "2"', but was never asked/)
49
65
 
50
66
  instance.size 3
51
67
  instance.size 4, '5'
52
- expect { instance.should have_been_asked_for_its(:size).with(1, '2') }.to \
68
+ expect { did_ask :size, with: [1, '2'] }.to \
53
69
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its size with `1, "2"', but got `3', `4, "5"'/)
54
70
  end
55
71
 
56
72
  example 'failure message for should not' do
57
73
  instance.size 1, '2'
58
- expect { instance.should_not have_been_asked_for_its(:size).with(1, '2') }.to \
74
+ expect { did_not_ask :size, with: [1, '2'] }.to \
59
75
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked for its size with `1, "2"'/)
60
76
  end
61
77
 
62
78
  describe 'integration with rspec argument_matchers' do
63
79
  it 'works with rspec matchers' do
64
- instance.should_not have_been_asked_for_its(:size).with(no_args)
80
+ did_not_ask :size, with: [no_args]
65
81
  instance.size(1)
66
- instance.should_not have_been_asked_for_its(:size).with(no_args)
82
+ did_not_ask :size, with: [no_args]
67
83
  instance.size
68
- instance.should have_been_asked_for_its(:size).with(no_args)
84
+ did_ask :size, with: [no_args]
69
85
 
70
- instance.should_not have_been_asked_for_its(:size).with(hash_including all: true)
86
+ did_not_ask :size, with: [hash_including(all: true)]
71
87
  instance.size any: false, all: true
72
- instance.should have_been_asked_for_its(:size).with(hash_including all: true)
73
- instance.should_not have_been_asked_for_its(:size).with(hash_including all: false)
88
+ did_ask :size, with: [hash_including(all: true)]
89
+ did_not_ask :size, with: [hash_including(all: false)]
74
90
  end
75
91
  end
76
92
  end
@@ -80,28 +96,28 @@ describe 'RSpec matchers', 'have_been_asked_for_its' do
80
96
  before { mocked_class.define :value, default: nil }
81
97
 
82
98
  example 'default use case' do
83
- instance.should have_been_asked_for_its(:value).times(0)
99
+ did_ask :value, times: 0
84
100
  instance.value
85
- instance.should have_been_asked_for_its(:value).times(1)
101
+ did_ask :value, times: 1
86
102
  instance.value
87
- instance.should have_been_asked_for_its(:value).times(2)
103
+ did_ask :value, times: 2
88
104
  end
89
105
 
90
106
  example 'failure message for should' do
91
- expect { instance.should have_been_asked_for_its(:value).times(1) }.to \
107
+ expect { did_ask :value, times: 1 }.to \
92
108
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time, but was asked 0 times/)
93
109
 
94
110
  instance.value
95
- expect { instance.should have_been_asked_for_its(:value).times(2) }.to \
111
+ expect { did_ask :value, times: 2 }.to \
96
112
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 2 times, but was asked 1 time/)
97
113
  end
98
114
 
99
115
  example 'failure message for should not' do
100
- expect { instance.should_not have_been_asked_for_its(:value).times(0) }.to \
116
+ expect { did_not_ask :value, times: 0 }.to \
101
117
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its value 0 times, but was/)
102
118
 
103
119
  instance.value
104
- expect { instance.should_not have_been_asked_for_its(:value).times(1) }.to \
120
+ expect { did_not_ask :value, times: 1 }.to \
105
121
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked for its value 1 time, but was/)
106
122
  end
107
123
  end
@@ -110,39 +126,56 @@ describe 'RSpec matchers', 'have_been_asked_for_its' do
110
126
  before { mocked_class.define :value, default: nil }
111
127
 
112
128
  example 'default use case' do
113
- instance.should have_been_asked_for_its(:value).times(0).with(1, '2')
114
- instance.should_not have_been_asked_for_its(:value).times(1).with(1, '2')
129
+ did_ask :value, times: 0, with: [1, '2']
130
+ did_not_ask :value, times: 1, with: [1, '2']
115
131
  instance.value
116
- instance.should have_been_asked_for_its(:value).times(0).with(1, '2')
117
- instance.should_not have_been_asked_for_its(:value).times(1).with(1, '2')
132
+ did_ask :value, times: 0, with: [1, '2']
133
+ did_not_ask :value, times: 1, with: [1, '2']
134
+
118
135
  instance.value 1, '2'
119
- instance.should have_been_asked_for_its(:value).times(1).with(1, '2')
136
+ did_ask :value, times: 1, with: [1, '2']
120
137
  instance.value 1, '2' # correct one
121
138
  instance.value 1, '3'
122
139
  instance.value 2, '2'
123
140
  instance.value 1, '2', 3
124
- instance.should have_been_asked_for_its(:value).times(2).with(1, '2')
125
- instance.should have_been_asked_for_its(:value).with(1, '2').times(2)
141
+ instance.send positive_assertion, send(matcher_name, :value).times(2).with(1, '2')
142
+ instance.send positive_assertion, send(matcher_name, :value).with(1, '2').times(2)
126
143
  end
127
144
 
128
145
  example 'failure message for should' do
129
- expect { instance.should have_been_asked_for_its(:value).times(1).with(1, '2') }.to \
146
+ expect { did_ask :value, times: 1, with: [1, '2'] }.to \
130
147
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time with `1, "2"', but was never asked/)
131
148
 
132
149
  instance.value 1, '2'
133
- expect { instance.should have_been_asked_for_its(:value).times(0).with(1, '2') }.to \
150
+ expect { did_ask :value, times: 0, with: [1, '2'] }.to \
134
151
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 0 times with `1, "2"', but was asked 1 time/)
135
152
 
136
153
  instance.value 1, '2'
137
- expect { instance.should have_been_asked_for_its(:value).times(1).with(1, '2') }.to \
154
+ expect { did_ask :value, times: 1, with: [1, '2'] }.to \
138
155
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked for its value 1 time with `1, "2"', but was asked 2 times/)
139
156
  end
140
157
 
141
158
  example 'failure message for should not' do
142
159
  instance.value 1, '2'
143
160
  instance.value 1, '2'
144
- expect { instance.should_not have_been_asked_for_its(:value).times(2).with(1, '2') }.to \
161
+ expect { did_not_ask :value, times: 2, with: [1, '2'] }.to \
145
162
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked for its value 2 times with `1, "2"'/)
146
163
  end
147
164
  end
148
165
  end
166
+
167
+ describe 'should/should_not have_been_asked_for_its' do
168
+ let(:positive_assertion) { :should }
169
+ let(:negative_assertion) { :should_not }
170
+ let(:matcher_name) { :have_been_asked_for_its }
171
+
172
+ it_behaves_like 'a noun matcher'
173
+ end
174
+
175
+ describe 'was/was_not asked_for' do
176
+ let(:positive_assertion) { :was }
177
+ let(:negative_assertion) { :was_not }
178
+ let(:matcher_name) { :asked_for }
179
+
180
+ it_behaves_like 'a noun matcher'
181
+ end
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for 'a predicate matcher' do
4
+ let(:mocked_class) { Surrogate.endow(Class.new).define :changed?, default: false }
5
+ let(:instance) { mocked_class.new }
6
+
7
+ def did_ask(argument, modifiers={})
8
+ assert!(positive_assertion, argument, modifiers)
9
+ end
10
+
11
+ def did_not_ask(argument, modifiers={})
12
+ assert!(negative_assertion, argument, modifiers)
13
+ end
14
+
15
+ def assert!(assertion, argument, modifiers)
16
+ matcher = send(matcher_name, argument)
17
+ matcher.send(:with, *modifiers[:with]) if modifiers.has_key? :with
18
+ matcher.send(:times, modifiers[:times]) if modifiers.has_key? :times
19
+ instance.send(assertion, matcher)
20
+ end
21
+
22
+ describe 'default use case' do
23
+ example 'passes if has been invoked at least once' do
24
+ did_not_ask :changed?
25
+ instance.changed?
26
+ did_ask :changed?
27
+ instance.changed?
28
+ did_ask :changed?
29
+ end
30
+
31
+ example 'failure message for should' do
32
+ expect { did_ask :changed? }.to \
33
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /was never asked if changed?/)
34
+ end
35
+
36
+ example 'failure message for should not' do
37
+ instance.changed?
38
+ expect { did_not_ask :changed? }.to \
39
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked if changed\?, but was asked 1 time/)
40
+
41
+ instance.changed?
42
+ expect { did_not_ask :changed? }.to \
43
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked if changed\?, but was asked 2 times/)
44
+ end
45
+ end
46
+
47
+
48
+ describe 'specifying which arguments it should have been invoked with' do
49
+
50
+ example 'default use case' do
51
+ did_not_ask :changed?, with: [1, 2, 3]
52
+ instance.changed? 1, 2
53
+ did_not_ask :changed?, with: [1, 2, 3]
54
+ instance.changed? 1, 2, 3
55
+ did_ask :changed?, with: [1, 2, 3]
56
+ end
57
+
58
+ example 'failure message for should' do
59
+ expect { did_ask :changed?, with: [1, '2'] }.to \
60
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? with `1, "2"', but was never asked/)
61
+
62
+ instance.changed? 3
63
+ instance.changed? 4, '5'
64
+ expect { did_ask :changed?, with: [1, '2'] }.to \
65
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? with `1, "2"', but got `3', `4, "5"'/)
66
+ end
67
+
68
+ example 'failure message for should not' do
69
+ instance.changed? 1, '2'
70
+ expect { did_not_ask :changed?, with: [1, '2'] }.to \
71
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked if changed\? with `1, "2"'/)
72
+ end
73
+
74
+ describe 'integration with rspec argument_matchers' do
75
+ it 'works with rspec matchers' do
76
+ did_not_ask :changed?, with: [no_args]
77
+ instance.changed?(1)
78
+ did_not_ask :changed?, with: [no_args]
79
+ instance.changed?
80
+ did_ask :changed?, with: [no_args]
81
+
82
+ did_not_ask :changed?, with: [hash_including(all: true)]
83
+ instance.changed? any: false, all: true
84
+ did_ask :changed?, with: [hash_including(all: true)]
85
+ did_not_ask :changed?, with: [hash_including(all: false)]
86
+ end
87
+ end
88
+ end
89
+
90
+
91
+ describe 'specifying number of times invoked' do
92
+
93
+ example 'default use case' do
94
+ did_ask :changed?, times: 0
95
+ instance.changed?
96
+ did_ask :changed?, times: 1
97
+ instance.changed?
98
+ did_ask :changed?, times: 2
99
+ end
100
+
101
+ example 'failure message for should' do
102
+ expect { did_ask :changed?, times: 1 }.to \
103
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? 1 time, but was asked 0 times/)
104
+
105
+ instance.changed?
106
+ expect { did_ask :changed?, times: 2 }.to \
107
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? 2 times, but was asked 1 time/)
108
+ end
109
+
110
+ example 'failure message for should not' do
111
+ expect { did_not_ask :changed?, times: 0 }.to \
112
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked if changed\? 0 times, but was/)
113
+
114
+ instance.changed?
115
+ expect { did_not_ask :changed?, times: 1 }.to \
116
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been asked if changed\? 1 time, but was/)
117
+ end
118
+ end
119
+
120
+ describe 'conjunction of with(args) and times(n)' do
121
+
122
+ example 'default use case' do
123
+ did_ask :changed?, times: 0, with: [1, '2']
124
+ did_not_ask :changed?, times: 1, with: [1, '2']
125
+ instance.changed?
126
+ did_ask :changed?, times: 0, with: [1, '2']
127
+ did_not_ask :changed?, times: 1, with: [1, '2']
128
+ instance.changed? 1, '2'
129
+ did_ask :changed?, times: 1, with: [1, '2']
130
+ instance.changed? 1, '2' # correct one
131
+ instance.changed? 1, '3'
132
+ instance.changed? 2, '2'
133
+ instance.changed? 1, '2', 3
134
+ instance.send positive_assertion, send(matcher_name, :changed?).times(2).with(1, '2')
135
+ instance.send positive_assertion, send(matcher_name, :changed?).with(1, '2').times(2)
136
+ end
137
+
138
+ example 'failure message for should' do
139
+ expect { did_ask :changed?, times: 1, with: [1, '2'] }.to \
140
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? 1 time with `1, "2"', but was never asked/)
141
+
142
+ instance.changed? 1, '2'
143
+ expect { did_ask :changed?, times: 0, with: [1, '2'] }.to \
144
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? 0 times with `1, "2"', but was asked 1 time/)
145
+
146
+ instance.changed? 1, '2'
147
+ expect { did_ask :changed?, times: 1, with: [1, '2'] }.to \
148
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been asked if changed\? 1 time with `1, "2"', but was asked 2 times/)
149
+ end
150
+
151
+ example 'failure message for should not' do
152
+ instance.changed? 1, '2'
153
+ instance.changed? 1, '2'
154
+ expect { did_not_ask :changed?, times: 2, with: [1, '2'] }.to \
155
+ raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been asked if changed\? 2 times with `1, "2"'/)
156
+ end
157
+ end
158
+ end
159
+
160
+ describe 'should/should_not have_been_asked_if' do
161
+ let(:positive_assertion) { :should }
162
+ let(:negative_assertion) { :should_not }
163
+ let(:matcher_name) { :have_been_asked_if }
164
+
165
+ it_behaves_like 'a predicate matcher'
166
+ end
167
+
168
+ describe 'was/was_not asked_if' do
169
+ let(:positive_assertion) { :was }
170
+ let(:negative_assertion) { :was_not }
171
+ let(:matcher_name) { :asked_if }
172
+
173
+ it_behaves_like 'a predicate matcher'
174
+ end
175
+
@@ -1,32 +1,48 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'RSpec matchers', 'have_been_told_to' do
3
+ shared_examples_for 'a verb matcher' do
4
+
4
5
  let(:mocked_class) { Surrogate.endow Class.new }
5
6
  let(:instance) { mocked_class.new }
6
7
 
8
+ def did(argument, modifiers={})
9
+ assert!(positive_assertion, argument, modifiers)
10
+ end
11
+
12
+ def did_not(argument, modifiers={})
13
+ assert!(negative_assertion, argument, modifiers)
14
+ end
15
+
16
+ def assert!(assertion, argument, modifiers)
17
+ matcher = send(matcher_name, argument)
18
+ matcher.send(:with, *modifiers[:with]) if modifiers.has_key? :with
19
+ matcher.send(:times, modifiers[:times]) if modifiers.has_key? :times
20
+ instance.send(assertion, matcher)
21
+ end
22
+
7
23
  describe 'default use case' do
8
24
  before { mocked_class.define :kick, default: [] }
9
25
 
10
26
  example 'passes if has been invoked at least once' do
11
- instance.should_not have_been_told_to :kick
27
+ did_not :kick
12
28
  instance.kick
13
- instance.should have_been_told_to :kick
29
+ did :kick
14
30
  instance.kick
15
- instance.should have_been_told_to :kick
31
+ did :kick
16
32
  end
17
33
 
18
34
  example 'failure message for should' do
19
- expect { instance.should have_been_told_to :kick }.to \
35
+ expect { did :kick }.to \
20
36
  raise_error(RSpec::Expectations::ExpectationNotMetError, /was never told to kick/)
21
37
  end
22
38
 
23
39
  example 'failure message for should not' do
24
40
  instance.kick
25
- expect { instance.should_not have_been_told_to :kick }.to \
41
+ expect { did_not :kick }.to \
26
42
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to kick, but was told to kick 1 time/)
27
43
 
28
44
  instance.kick
29
- expect { instance.should_not have_been_told_to :kick }.to \
45
+ expect { did_not :kick }.to \
30
46
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to kick, but was told to kick 2 times/)
31
47
  end
32
48
  end
@@ -36,26 +52,26 @@ describe 'RSpec matchers', 'have_been_told_to' do
36
52
  before { mocked_class.define :smile, default: nil }
37
53
 
38
54
  example 'default use case' do
39
- instance.should_not have_been_told_to(:smile).with(1, 2, 3)
55
+ did_not :smile, with: [1,2,3]
40
56
  instance.smile 1, 2
41
- instance.should_not have_been_told_to(:smile).with(1, 2, 3)
57
+ did_not :smile, with: [1,2,3]
42
58
  instance.smile 1, 2, 3
43
- instance.should have_been_told_to(:smile).with(1, 2, 3)
59
+ did :smile, with: [1,2,3]
44
60
  end
45
61
 
46
62
  example 'failure message for should' do
47
- expect { instance.should have_been_told_to(:smile).with(1, '2') }.to \
63
+ expect { did :smile, with: [1,'2'] }.to \
48
64
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to smile with `1, "2"', but was never told to/)
49
65
 
50
66
  instance.smile 3
51
67
  instance.smile 4, '5'
52
- expect { instance.should have_been_told_to(:smile).with(1, '2') }.to \
68
+ expect { did :smile, with: [1,'2'] }.to \
53
69
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to smile with `1, "2"', but got `3', `4, "5"'/)
54
70
  end
55
71
 
56
72
  example 'failure message for should not' do
57
73
  instance.smile 1, '2'
58
- expect { instance.should_not have_been_told_to(:smile).with(1, '2') }.to \
74
+ expect { did_not :smile, with: [1,'2'] }.to \
59
75
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been told to smile with `1, "2"'/)
60
76
  end
61
77
  end
@@ -65,28 +81,28 @@ describe 'RSpec matchers', 'have_been_told_to' do
65
81
  before { mocked_class.define :wink, default: nil }
66
82
 
67
83
  example 'default use case' do
68
- instance.should have_been_told_to(:wink).times(0)
84
+ did :wink, times: 0
69
85
  instance.wink
70
- instance.should have_been_told_to(:wink).times(1)
86
+ did :wink, times: 1
71
87
  instance.wink
72
- instance.should have_been_told_to(:wink).times(2)
88
+ did :wink, times: 2
73
89
  end
74
90
 
75
91
  example 'failure message for should' do
76
- expect { instance.should have_been_told_to(:wink).times(1) }.to \
92
+ expect { did :wink, times: 1 }.to \
77
93
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time but was told to wink 0 times/)
78
94
 
79
95
  instance.wink
80
- expect { instance.should have_been_told_to(:wink).times(2) }.to \
96
+ expect { did :wink, times: 2 }.to \
81
97
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 2 times but was told to wink 1 time/)
82
98
  end
83
99
 
84
100
  example 'failure message for should not' do
85
- expect { instance.should_not have_been_told_to(:wink).times(0) }.to \
101
+ expect { did_not :wink, times: 0 }.to \
86
102
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to wink 0 times, but was/)
87
103
 
88
104
  instance.wink
89
- expect { instance.should_not have_been_told_to(:wink).times(1) }.to \
105
+ expect { did_not :wink, times: 1 }.to \
90
106
  raise_error(RSpec::Expectations::ExpectationNotMetError, /shouldn't have been told to wink 1 time, but was/)
91
107
  end
92
108
  end
@@ -95,39 +111,56 @@ describe 'RSpec matchers', 'have_been_told_to' do
95
111
  before { mocked_class.define :wink, default: nil }
96
112
 
97
113
  example 'default use case' do
98
- instance.should have_been_told_to(:wink).times(0).with(1, '2')
99
- instance.should_not have_been_told_to(:wink).times(1).with(1, '2')
114
+ did :wink, times: 0, with: [1, '2']
115
+ did_not :wink, times: 1, with: [1, '2']
100
116
  instance.wink
101
- instance.should have_been_told_to(:wink).times(0).with(1, '2')
102
- instance.should_not have_been_told_to(:wink).times(1).with(1, '2')
117
+ did :wink, times: 0, with: [1, '2']
118
+ did_not :wink, times: 1, with: [1, '2']
103
119
  instance.wink 1, '2'
104
- instance.should have_been_told_to(:wink).times(1).with(1, '2')
120
+ did :wink, times: 1, with: [1, '2']
105
121
  instance.wink 1, '2' # correct one
106
122
  instance.wink 1, '3'
107
123
  instance.wink 2, '2'
108
124
  instance.wink 1, '2', 3
109
- instance.should have_been_told_to(:wink).times(2).with(1, '2')
110
- instance.should have_been_told_to(:wink).with(1, '2').times(2)
125
+ instance.send positive_assertion, send(matcher_name, :wink).times(2).with(1, '2')
126
+ instance.send positive_assertion, send(matcher_name, :wink).with(1, '2').times(2)
111
127
  end
112
128
 
113
129
  example 'failure message for should' do
114
- expect { instance.should have_been_told_to(:wink).times(1).with(1, '2') }.to \
130
+ expect { did :wink, times: 1, with: [1, '2'] }.to \
115
131
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time with `1, "2"', but was never told to/)
116
132
 
117
133
  instance.wink 1, '2'
118
- expect { instance.should have_been_told_to(:wink).times(0).with(1, '2') }.to \
134
+ expect { did :wink, times: 0, with: [1, '2'] }.to \
119
135
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 0 times with `1, "2"', but got it 1 time/)
120
136
 
121
137
  instance.wink 1, '2'
122
- expect { instance.should have_been_told_to(:wink).times(1).with(1, '2') }.to \
138
+ expect { did :wink, times: 1, with: [1, '2'] }.to \
123
139
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should have been told to wink 1 time with `1, "2"', but got it 2 times/)
124
140
  end
125
141
 
126
142
  example 'failure message for should not' do
127
143
  instance.wink 1, '2'
128
144
  instance.wink 1, '2'
129
- expect { instance.should_not have_been_told_to(:wink).times(2).with(1, '2') }.to \
145
+ expect { did_not :wink, times: 2, with: [1, '2'] }.to \
130
146
  raise_error(RSpec::Expectations::ExpectationNotMetError, /should not have been told to wink 2 times with `1, "2"'/)
131
147
  end
132
148
  end
133
149
  end
150
+
151
+
152
+ describe 'should/should_not have_been_told_to' do
153
+ let(:positive_assertion) { :should }
154
+ let(:negative_assertion) { :should_not }
155
+ let(:matcher_name) { :have_been_told_to }
156
+
157
+ it_behaves_like 'a verb matcher'
158
+ end
159
+
160
+ describe 'was/was_not told_to' do
161
+ let(:positive_assertion) { :was }
162
+ let(:negative_assertion) { :was_not }
163
+ let(:matcher_name) { :told_to }
164
+
165
+ it_behaves_like 'a verb matcher'
166
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surrogate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-20 00:00:00.000000000 Z
12
+ date: 2012-06-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindable_block
16
- requirement: &70339421986340 !ruby/object:Gem::Requirement
16
+ requirement: &70359043120580 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.0.5.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70339421986340
24
+ version_requirements: *70359043120580
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70339421985140 !ruby/object:Gem::Requirement
27
+ requirement: &70359043118940 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 2.8.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70339421985140
35
+ version_requirements: *70359043118940
36
36
  description: Framework to aid in handrolling mock/spy objects.
37
37
  email:
38
38
  - josh.cheek@gmail.com
@@ -55,6 +55,7 @@ files:
55
55
  - lib/surrogate/rspec.rb
56
56
  - lib/surrogate/rspec/abstract_failure_message.rb
57
57
  - lib/surrogate/rspec/have_been_asked_for_its.rb
58
+ - lib/surrogate/rspec/have_been_asked_if.rb
58
59
  - lib/surrogate/rspec/have_been_initialized_with.rb
59
60
  - lib/surrogate/rspec/have_been_told_to.rb
60
61
  - lib/surrogate/rspec/invocation_matcher.rb
@@ -66,9 +67,10 @@ files:
66
67
  - spec/acceptance_spec.rb
67
68
  - spec/defining_api_methods_spec.rb
68
69
  - spec/rspec/block_support_spec.rb
69
- - spec/rspec/have_been_asked_for_its_spec.rb
70
- - spec/rspec/have_been_initialized_with_spec.rb
71
- - spec/rspec/have_been_told_to_spec.rb
70
+ - spec/rspec/matchers_for_initialization_spec.rb
71
+ - spec/rspec/matchers_for_nouns_spec.rb
72
+ - spec/rspec/matchers_for_predicates_spec.rb
73
+ - spec/rspec/matchers_for_verbs_spec.rb
72
74
  - spec/rspec/messages_spec.rb
73
75
  - spec/rspec/rspec_mocks_integration_spec.rb
74
76
  - spec/rspec/substitute_for_spec.rb
@@ -103,9 +105,10 @@ test_files:
103
105
  - spec/acceptance_spec.rb
104
106
  - spec/defining_api_methods_spec.rb
105
107
  - spec/rspec/block_support_spec.rb
106
- - spec/rspec/have_been_asked_for_its_spec.rb
107
- - spec/rspec/have_been_initialized_with_spec.rb
108
- - spec/rspec/have_been_told_to_spec.rb
108
+ - spec/rspec/matchers_for_initialization_spec.rb
109
+ - spec/rspec/matchers_for_nouns_spec.rb
110
+ - spec/rspec/matchers_for_predicates_spec.rb
111
+ - spec/rspec/matchers_for_verbs_spec.rb
109
112
  - spec/rspec/messages_spec.rb
110
113
  - spec/rspec/rspec_mocks_integration_spec.rb
111
114
  - spec/rspec/substitute_for_spec.rb