surrogate 0.5.0 → 0.5.1

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