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 +30 -3
- data/lib/surrogate/endower.rb +14 -0
- data/lib/surrogate/rspec/have_been_asked_if.rb +71 -0
- data/lib/surrogate/rspec.rb +35 -7
- data/lib/surrogate/version.rb +1 -1
- data/spec/rspec/{have_been_initialized_with_spec.rb → matchers_for_initialization_spec.rb} +29 -1
- data/spec/rspec/{have_been_asked_for_its_spec.rb → matchers_for_nouns_spec.rb} +70 -37
- data/spec/rspec/matchers_for_predicates_spec.rb +175 -0
- data/spec/rspec/{have_been_told_to_spec.rb → matchers_for_verbs_spec.rb} +64 -31
- metadata +15 -12
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?)
|
data/lib/surrogate/endower.rb
CHANGED
@@ -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
|
data/lib/surrogate/rspec.rb
CHANGED
@@ -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(
|
23
|
-
HaveBeenToldTo.new
|
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
|
27
|
-
HaveBeenAskedForIts.new
|
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'
|
data/lib/surrogate/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
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
|
-
|
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
|
-
|
27
|
+
did_not_ask :name
|
12
28
|
instance.name
|
13
|
-
|
29
|
+
did_ask :name
|
14
30
|
instance.name
|
15
|
-
|
31
|
+
did_ask :name
|
16
32
|
end
|
17
33
|
|
18
34
|
example 'failure message for should' do
|
19
|
-
expect {
|
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 {
|
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 {
|
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
|
-
|
55
|
+
did_not_ask :size, with: [1, 2, 3]
|
40
56
|
instance.size 1, 2
|
41
|
-
|
57
|
+
did_not_ask :size, with: [1, 2, 3]
|
42
58
|
instance.size 1, 2, 3
|
43
|
-
|
59
|
+
did_ask :size, with: [1, 2, 3]
|
44
60
|
end
|
45
61
|
|
46
62
|
example 'failure message for should' do
|
47
|
-
expect {
|
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 {
|
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 {
|
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
|
-
|
80
|
+
did_not_ask :size, with: [no_args]
|
65
81
|
instance.size(1)
|
66
|
-
|
82
|
+
did_not_ask :size, with: [no_args]
|
67
83
|
instance.size
|
68
|
-
|
84
|
+
did_ask :size, with: [no_args]
|
69
85
|
|
70
|
-
|
86
|
+
did_not_ask :size, with: [hash_including(all: true)]
|
71
87
|
instance.size any: false, all: true
|
72
|
-
|
73
|
-
|
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
|
-
|
99
|
+
did_ask :value, times: 0
|
84
100
|
instance.value
|
85
|
-
|
101
|
+
did_ask :value, times: 1
|
86
102
|
instance.value
|
87
|
-
|
103
|
+
did_ask :value, times: 2
|
88
104
|
end
|
89
105
|
|
90
106
|
example 'failure message for should' do
|
91
|
-
expect {
|
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 {
|
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 {
|
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 {
|
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
|
-
|
114
|
-
|
129
|
+
did_ask :value, times: 0, with: [1, '2']
|
130
|
+
did_not_ask :value, times: 1, with: [1, '2']
|
115
131
|
instance.value
|
116
|
-
|
117
|
-
|
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
|
-
|
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.
|
125
|
-
instance.
|
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 {
|
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 {
|
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 {
|
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 {
|
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
|
-
|
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
|
-
|
27
|
+
did_not :kick
|
12
28
|
instance.kick
|
13
|
-
|
29
|
+
did :kick
|
14
30
|
instance.kick
|
15
|
-
|
31
|
+
did :kick
|
16
32
|
end
|
17
33
|
|
18
34
|
example 'failure message for should' do
|
19
|
-
expect {
|
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 {
|
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 {
|
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
|
-
|
55
|
+
did_not :smile, with: [1,2,3]
|
40
56
|
instance.smile 1, 2
|
41
|
-
|
57
|
+
did_not :smile, with: [1,2,3]
|
42
58
|
instance.smile 1, 2, 3
|
43
|
-
|
59
|
+
did :smile, with: [1,2,3]
|
44
60
|
end
|
45
61
|
|
46
62
|
example 'failure message for should' do
|
47
|
-
expect {
|
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 {
|
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 {
|
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
|
-
|
84
|
+
did :wink, times: 0
|
69
85
|
instance.wink
|
70
|
-
|
86
|
+
did :wink, times: 1
|
71
87
|
instance.wink
|
72
|
-
|
88
|
+
did :wink, times: 2
|
73
89
|
end
|
74
90
|
|
75
91
|
example 'failure message for should' do
|
76
|
-
expect {
|
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 {
|
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 {
|
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 {
|
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
|
-
|
99
|
-
|
114
|
+
did :wink, times: 0, with: [1, '2']
|
115
|
+
did_not :wink, times: 1, with: [1, '2']
|
100
116
|
instance.wink
|
101
|
-
|
102
|
-
|
117
|
+
did :wink, times: 0, with: [1, '2']
|
118
|
+
did_not :wink, times: 1, with: [1, '2']
|
103
119
|
instance.wink 1, '2'
|
104
|
-
|
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.
|
110
|
-
instance.
|
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 {
|
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 {
|
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 {
|
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 {
|
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.
|
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-
|
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: &
|
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: *
|
24
|
+
version_requirements: *70359043120580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
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: *
|
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/
|
70
|
-
- spec/rspec/
|
71
|
-
- spec/rspec/
|
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/
|
107
|
-
- spec/rspec/
|
108
|
-
- spec/rspec/
|
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
|