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 +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
|