crispy 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +18 -4
- data/ChangeLog.md +10 -0
- data/Gemfile +2 -0
- data/README.md +99 -2
- data/crispy.gemspec +3 -2
- data/lib/crispy/crispy_internal/class_spy.rb +104 -0
- data/lib/crispy/crispy_internal/const_changer.rb +42 -0
- data/lib/crispy/crispy_internal/spy.rb +20 -18
- data/lib/crispy/crispy_internal/spy_mixin.rb +65 -19
- data/lib/crispy/crispy_received_message.rb +52 -0
- data/lib/crispy/crispy_received_message_with_receiver.rb +61 -0
- data/lib/crispy/crispy_world.rb +13 -0
- data/lib/crispy/version.rb +1 -1
- data/lib/crispy.rb +8 -11
- data/test/doctest-fixtures/your_cool_class.rb +8 -0
- data/test/test_crispy.rb +335 -5
- data/test/test_helper.rb +4 -0
- metadata +25 -5
- data/lib/crispy/crispy/received_message.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5a304875b84ee789d83ba6420f4b57a2cd769d3
|
4
|
+
data.tar.gz: 50dddf1394a740c51c7a15dbfd5d4bd3227388b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 469caadde79084134b26358634de2830d156233e938b4ad2c1a21dd6653d0bd50d019530e6c5ad80bcf9b5e59526b135572bc8939b5d160b2f4a3f10129d79d8
|
7
|
+
data.tar.gz: 902018025f544c073758117e5072896cb7dbf5b6cbc2a41f52b6116036a485a24ff23090e36718d94fdabe0ca7b9a27c21fa18db2bf61be6e255247029c2c58d
|
data/.travis.yml
CHANGED
@@ -3,9 +3,23 @@ install:
|
|
3
3
|
- gem install bundler
|
4
4
|
- bundle
|
5
5
|
rvm:
|
6
|
-
-
|
6
|
+
- ruby-head
|
7
|
+
- 2.2.0-preview1
|
8
|
+
- 2.1.3
|
7
9
|
- 2.0.0
|
8
|
-
- rbx-2
|
9
10
|
script:
|
10
|
-
- bundle exec
|
11
|
-
- bundle exec
|
11
|
+
- CODECLIMATE_REPO_TOKEN=fe75ea4329c1e131ef79de66f8ba2f605fa2fd352bbbd61fed5024cb6eaaba73 bundle exec rubydoctest README.md
|
12
|
+
- CODECLIMATE_REPO_TOKEN=fe75ea4329c1e131ef79de66f8ba2f605fa2fd352bbbd61fed5024cb6eaaba73 bundle exec ruby test/test_crispy.rb
|
13
|
+
notifications:
|
14
|
+
email:
|
15
|
+
recipients:
|
16
|
+
- whosekiteneverfly@gmail.com
|
17
|
+
on_success: never
|
18
|
+
on_failure: never
|
19
|
+
addons:
|
20
|
+
code_climate:
|
21
|
+
repo_token: 4329c1e131ef79de66f8ba2f605fa2fd352bbbd61fed5024cb6eaaba73
|
22
|
+
matrix:
|
23
|
+
allow_failures:
|
24
|
+
- rvm: ruby-head
|
25
|
+
- rvm: 2.2.0-preview1
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# 0.2.0 (2014.11.1)
|
2
|
+
|
3
|
+
- New Feature: `stub_const`. [#11](https://github.com/igrep/crispy/pull/11)
|
4
|
+
- New Feature: `spy_into_instances`, `spy_of_instances`. [#17](https://github.com/igrep/crispy/pull/17)
|
5
|
+
- New Feature: `spy().stop`, `spy().restart`. [#17](https://github.com/igrep/crispy/pull/17)
|
6
|
+
- Compatibility Change: change module structure. [#11](https://github.com/igrep/crispy/pull/11)
|
7
|
+
- Now public modules are prefixed with `Crispy` instead of `Crispy::`.
|
8
|
+
- Because it seems that we can't refer with `Crispy::World` when including the top level `::Crispy` module.
|
9
|
+
- So now we can refer with `CrispyWorld` by including `::Crispy`
|
10
|
+
|
1
11
|
# 0.1.2 (2014.8.24)
|
2
12
|
|
3
13
|
- Support Ruby 2.0 correctly.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Crispy
|
2
2
|
|
3
|
+
[](https://codeclimate.com/github/igrep/crispy)
|
4
|
+
[](https://codeclimate.com/github/igrep/crispy)
|
5
|
+
[](https://travis-ci.org/igrep/crispy)
|
6
|
+
[](http://badge.fury.io/rb/crispy)
|
7
|
+
|
3
8
|
Test Spy for Any Object in Ruby.
|
4
9
|
|
5
10
|
## Features
|
@@ -30,7 +35,7 @@ Or install it yourself as:
|
|
30
35
|
doctest_require: './test/doctest-fixtures/your_cool_class.rb'
|
31
36
|
-->
|
32
37
|
|
33
|
-
### Spy on
|
38
|
+
### Spy on an Object
|
34
39
|
|
35
40
|
```ruby
|
36
41
|
>> require 'crispy'
|
@@ -96,7 +101,7 @@ Each argument is compared by `==` method.
|
|
96
101
|
#### Get more detailed log
|
97
102
|
|
98
103
|
You can check arbitrary received methods with the familliar Array's (and of course including Enumerable's!) methods such as `any?`, `all`, `first`, `[]`, `index`.
|
99
|
-
Because `spy(object).received_messages` returns an array of `
|
104
|
+
Because `spy(object).received_messages` returns an array of `CrispyReceivedMessage` instances.
|
100
105
|
**You don't have to remember the tons of matchers for received arguments any more!!**
|
101
106
|
|
102
107
|
```ruby
|
@@ -113,6 +118,76 @@ Because `spy(object).received_messages` returns an array of `Crispy::ReceivedMes
|
|
113
118
|
=> true
|
114
119
|
```
|
115
120
|
|
121
|
+
### Spy on Instances of a Class
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
>> spy_into_instances(YourCoolClass)
|
125
|
+
>> instance1 = YourCoolClass.new
|
126
|
+
>> instance2 = YourCoolClass.new
|
127
|
+
|
128
|
+
>> instance1.your_cool_method 'and', 'args'
|
129
|
+
>> instance2.your_lovely_method
|
130
|
+
>> instance2.your_lovely_method 'again!'
|
131
|
+
>> instance1.your_finalizer 'cleaning up...'
|
132
|
+
```
|
133
|
+
|
134
|
+
You can check methods called by all instances of a class by the same query methods wth spy.
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
>> spy_of_instances(YourCoolClass).received? :your_cool_method, 'and', 'args'
|
138
|
+
=> true
|
139
|
+
|
140
|
+
>> spy_of_instances(YourCoolClass).count_received :your_lovely_method
|
141
|
+
=> 2
|
142
|
+
|
143
|
+
>> spy_of_instances(YourCoolClass).received_messages.last.method_name == :your_finalizer
|
144
|
+
=> true
|
145
|
+
```
|
146
|
+
|
147
|
+
In addition, you can check which instance calles a method as well as its arguments.
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
>> spy_of_instances(YourCoolClass).received_with_receiver? instance1, :your_cool_method
|
151
|
+
=> true
|
152
|
+
>> spy_of_instances(YourCoolClass).received_with_receiver? instance2, :your_cool_method
|
153
|
+
=> false
|
154
|
+
|
155
|
+
>> spy_of_instances(YourCoolClass).count_received_with_receiver instance1, :your_lovely_method
|
156
|
+
=> 0
|
157
|
+
>> spy_of_instances(YourCoolClass).count_received_with_receiver instance2, :your_lovely_method
|
158
|
+
=> 2
|
159
|
+
|
160
|
+
>> spy_of_instances(YourCoolClass).received_messages_with_receiver.last.receiver == instance1
|
161
|
+
=> true
|
162
|
+
```
|
163
|
+
|
164
|
+
Note that `spy_of_instances` stops to spy after called methods with `with_receiver` (or `with_receiver?`) prefix.
|
165
|
+
This is to prevent the spy from unexpectedly logging methods used to compare its receiver (such as `==`).
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
>> spy_into_instances(YourCoolClass::Again)
|
169
|
+
>> instance = YourCoolClass::Again.new
|
170
|
+
|
171
|
+
>> instance.your_another_method
|
172
|
+
>> # Stops spying here.
|
173
|
+
>> spy_of_instances(YourCoolClass::Again).received_with_receiver? instance, :your_another_method
|
174
|
+
|
175
|
+
>> # Perhaps you don't want to log methods in test code.
|
176
|
+
>> instance.some_method_for_testing
|
177
|
+
>> spy_of_instances(YourCoolClass::Again).received? :some_method_for_testing
|
178
|
+
>> false
|
179
|
+
```
|
180
|
+
|
181
|
+
If you want to restart spying, use `restart` method literally.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
>> spy_into_instances(YourCoolClass::Again).restart
|
185
|
+
|
186
|
+
>> instance.some_method_for_testing
|
187
|
+
>> spy_of_instances(YourCoolClass::Again).received? :some_method_for_testing
|
188
|
+
>> true
|
189
|
+
```
|
190
|
+
|
116
191
|
### Stub Methods of a Spy
|
117
192
|
|
118
193
|
```ruby
|
@@ -141,6 +216,28 @@ Because `spy(object).received_messages` returns an array of `Crispy::ReceivedMes
|
|
141
216
|
=> "can be stubbed."
|
142
217
|
```
|
143
218
|
|
219
|
+
### Stub Constants
|
220
|
+
|
221
|
+
Specify the **fully qualified name of the constant** instead of the constant itself.
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
>> YourCoolClass::YOUR_COOL_CONST
|
225
|
+
=> "value before stubbed"
|
226
|
+
|
227
|
+
>> stub_const 'YourCoolClass::YOUR_COOL_CONST', 'more cool value!'
|
228
|
+
>> YourCoolClass::YOUR_COOL_CONST
|
229
|
+
=> "more cool value!"
|
230
|
+
```
|
231
|
+
|
232
|
+
Then you can recover the stubbed constant value by `CrispyWorld.reset`.
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
>> CrispyWorld.reset
|
236
|
+
|
237
|
+
>> YourCoolClass::YOUR_COOL_CONST
|
238
|
+
=> "value before stubbed"
|
239
|
+
```
|
240
|
+
|
144
241
|
## Contributing
|
145
242
|
|
146
243
|
1. Fork it ( https://github.com/igrep/crispy/fork )
|
data/crispy.gemspec
CHANGED
@@ -7,9 +7,9 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.version = Crispy::VERSION
|
8
8
|
spec.authors = ["Yamamoto Yuji"]
|
9
9
|
spec.email = ["whosekiteneverfly@gmail.com"]
|
10
|
-
spec.summary = %q{Test spy for any object
|
10
|
+
spec.summary = %q{Test spy for any object.}
|
11
11
|
spec.description =
|
12
|
-
"Test spy for any object
|
12
|
+
"Test spy for any object.\n" \
|
13
13
|
"It makes mocks obsolete so you don't have to be worried about " \
|
14
14
|
"where to put the expectations (i.e. before or after the subject method)."
|
15
15
|
spec.homepage = "https://github.com/igrep/crispy"
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "minitest", "~> 5.4"
|
26
26
|
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "byebug"
|
27
28
|
spec.add_development_dependency "rubydoctest"
|
28
29
|
|
29
30
|
spec.required_ruby_version = '>= 2.0'
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'crispy/crispy_received_message_with_receiver'
|
2
|
+
require 'crispy/crispy_internal/spy_mixin'
|
3
|
+
require 'crispy/crispy_internal/with_stubber'
|
4
|
+
|
5
|
+
module Crispy
|
6
|
+
module CrispyInternal
|
7
|
+
class ClassSpy < ::Module
|
8
|
+
include SpyMixin
|
9
|
+
#include WithStubber
|
10
|
+
|
11
|
+
@registry = {}
|
12
|
+
|
13
|
+
def initialize klass#, stubs_map = {}
|
14
|
+
spy = self
|
15
|
+
super() do
|
16
|
+
define_method(:__CRISPY_CLASS_SPY__) { spy }
|
17
|
+
end
|
18
|
+
|
19
|
+
@received_messages_with_receiver = []
|
20
|
+
initialize_spy
|
21
|
+
|
22
|
+
#initialize_stubber stubs_map
|
23
|
+
#prepend_stubber klass
|
24
|
+
|
25
|
+
prepend_features klass
|
26
|
+
self.class.register spy: spy, of_class: klass
|
27
|
+
end
|
28
|
+
|
29
|
+
def received_messages
|
30
|
+
@received_messages_with_receiver.map {|m| m.received_message }
|
31
|
+
end
|
32
|
+
|
33
|
+
def received_messages_with_receiver
|
34
|
+
# stop spying in advance to prevent from unexpectedly spying receiver's methods in test code.
|
35
|
+
self.stop
|
36
|
+
@received_messages_with_receiver
|
37
|
+
end
|
38
|
+
|
39
|
+
COMMON_RECEIVED_MESSAGE_METHODS_DEFINITION.each do|method_name, core_definition|
|
40
|
+
method_name_with_receiver = method_name.sub(/\??\z/) do|question_mark|
|
41
|
+
"_with_receiver#{question_mark}"
|
42
|
+
end
|
43
|
+
|
44
|
+
binding.eval(<<-END, __FILE__, (__LINE__ + 1))
|
45
|
+
def #{method_name_with_receiver} receiver, received_method_name, *received_arguments, &received_block
|
46
|
+
assert_symbol! received_method_name
|
47
|
+
if received_arguments.empty? and received_block.nil?
|
48
|
+
recevier_and_received_method_name = [receiver, received_method_name]
|
49
|
+
received_messages_with_receiver.map do|received_message_with_receiver|
|
50
|
+
[received_message_with_receiver.receiver, received_message_with_receiver.method_name]
|
51
|
+
end.#{sprintf(core_definition, 'recevier_and_received_method_name')}
|
52
|
+
else
|
53
|
+
received_message_with_receiver = ::Crispy::CrispyReceivedMessageWithReceiver.new(
|
54
|
+
receiver, received_method_name, *received_arguments, &received_block
|
55
|
+
)
|
56
|
+
received_messages_with_receiver.#{sprintf(core_definition, 'received_message_with_receiver')}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
END
|
60
|
+
end
|
61
|
+
|
62
|
+
def erase_log
|
63
|
+
@received_messages_with_receiver.clear
|
64
|
+
end
|
65
|
+
|
66
|
+
def append_received_message_with_receiver receiver, method_name, *arguments, &attached_block
|
67
|
+
if @spying
|
68
|
+
@received_messages_with_receiver <<
|
69
|
+
::Crispy::CrispyReceivedMessageWithReceiver.new(receiver, method_name, *arguments, &attached_block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def define_wrapper method_name
|
74
|
+
define_method method_name do|*arguments, &attached_block|
|
75
|
+
__CRISPY_CLASS_SPY__.append_received_message_with_receiver self, method_name, *arguments, &attached_block
|
76
|
+
|
77
|
+
super(*arguments, &attached_block)
|
78
|
+
end
|
79
|
+
method_name
|
80
|
+
end
|
81
|
+
private :define_wrapper
|
82
|
+
|
83
|
+
def self.new klass#, stubs_map = {}
|
84
|
+
spy = self.of_class(klass)
|
85
|
+
if spy
|
86
|
+
spy.restart
|
87
|
+
spy.erase_log
|
88
|
+
spy
|
89
|
+
else
|
90
|
+
super
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.register(spy: nil, of_class: nil)
|
95
|
+
@registry[of_class] = spy
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.of_class(klass)
|
99
|
+
@registry[klass]
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Crispy
|
2
|
+
module CrispyInternal
|
3
|
+
module ConstChanger
|
4
|
+
|
5
|
+
@registry = {}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def change_by_full_name full_const_name, value
|
10
|
+
const_names = full_const_name.split('::'.freeze)
|
11
|
+
|
12
|
+
const_names.shift if const_names.first.empty?
|
13
|
+
|
14
|
+
target_const_name = const_names.pop
|
15
|
+
|
16
|
+
module_containing_target_const =
|
17
|
+
const_names.inject(::Kernel) do|const_value, const_name|
|
18
|
+
const_value.const_get const_name
|
19
|
+
end
|
20
|
+
|
21
|
+
saved_value = module_containing_target_const.module_eval do
|
22
|
+
remove_const target_const_name
|
23
|
+
end
|
24
|
+
module_containing_target_const.const_set target_const_name, value
|
25
|
+
|
26
|
+
saved_value
|
27
|
+
end
|
28
|
+
|
29
|
+
def save full_const_name, value
|
30
|
+
@registry[full_const_name] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
def recover_all
|
34
|
+
@registry.each do|full_const_name, saved_value|
|
35
|
+
self.change_by_full_name(full_const_name, saved_value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'crispy/
|
1
|
+
require 'crispy/crispy_received_message'
|
2
2
|
require 'crispy/crispy_internal/spy_mixin'
|
3
3
|
require 'crispy/crispy_internal/with_stubber'
|
4
4
|
|
@@ -8,9 +8,17 @@ module Crispy
|
|
8
8
|
include SpyMixin
|
9
9
|
include WithStubber
|
10
10
|
|
11
|
+
attr_reader :received_messages
|
12
|
+
|
11
13
|
def initialize target, stubs_map = {}
|
12
|
-
super()
|
14
|
+
super() do
|
15
|
+
spy = self
|
16
|
+
define_method(:__CRISPY_SPY__) { spy }
|
17
|
+
end
|
18
|
+
|
13
19
|
@received_messages = []
|
20
|
+
initialize_spy
|
21
|
+
|
14
22
|
singleton_class =
|
15
23
|
class << target
|
16
24
|
self
|
@@ -19,29 +27,23 @@ module Crispy
|
|
19
27
|
prepend_stubber singleton_class
|
20
28
|
|
21
29
|
prepend_features singleton_class
|
22
|
-
target.__CRISPY_SPY__ = self
|
23
30
|
end
|
24
31
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
self.module_eval { public define_wrapper(method_name) }
|
29
|
-
end
|
30
|
-
klass.protected_instance_methods.each do|method_name|
|
31
|
-
self.module_eval { protected define_wrapper(method_name) }
|
32
|
-
end
|
33
|
-
klass.private_instance_methods.each do|method_name|
|
34
|
-
self.module_eval { private define_wrapper(method_name) }
|
35
|
-
end
|
32
|
+
def erase_log
|
33
|
+
@received_messages.clear
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
36
|
+
def append_received_message method_name, *arguments, &attached_block
|
37
|
+
if @spying
|
38
|
+
@received_messages <<
|
39
|
+
::Crispy::CrispyReceivedMessage.new(method_name, *arguments, &attached_block)
|
40
|
+
end
|
39
41
|
end
|
40
42
|
|
41
43
|
def define_wrapper method_name
|
42
44
|
define_method method_name do|*arguments, &attached_block|
|
43
|
-
|
44
|
-
|
45
|
+
__CRISPY_SPY__.append_received_message(method_name, *arguments, &attached_block)
|
46
|
+
|
45
47
|
super(*arguments, &attached_block)
|
46
48
|
end
|
47
49
|
method_name
|
@@ -1,34 +1,80 @@
|
|
1
|
-
require 'crispy/
|
1
|
+
require 'crispy/crispy_received_message'
|
2
2
|
|
3
3
|
module Crispy
|
4
4
|
module CrispyInternal
|
5
5
|
module SpyMixin
|
6
6
|
|
7
|
-
|
7
|
+
BLACK_LISTED_METHODS = [
|
8
|
+
:__CRISPY_CLASS_SPY__,
|
9
|
+
:__CRISPY_SPY__,
|
10
|
+
]
|
8
11
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def received_messages
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def erase_log
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def stop
|
21
|
+
@spying = false
|
15
22
|
end
|
16
23
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
24
|
+
def restart
|
25
|
+
@spying = true
|
26
|
+
end
|
27
|
+
|
28
|
+
COMMON_RECEIVED_MESSAGE_METHODS_DEFINITION = {
|
29
|
+
'received?' => 'include? %s',
|
30
|
+
'received_once?' => 'one? {|self_thing| self_thing == %s }',
|
31
|
+
'count_received' => 'count %s',
|
32
|
+
}
|
33
|
+
|
34
|
+
COMMON_RECEIVED_MESSAGE_METHODS_DEFINITION.each do|method_name, core_definition|
|
35
|
+
binding.eval(<<-END, __FILE__, (__LINE__ + 1))
|
36
|
+
def #{method_name} received_method_name, *received_arguments, &received_block
|
37
|
+
assert_symbol! received_method_name
|
38
|
+
if received_arguments.empty? and received_block.nil?
|
39
|
+
received_messages.map(&:method_name).#{sprintf(core_definition, 'received_method_name')}
|
40
|
+
else
|
41
|
+
received_message = ::Crispy::CrispyReceivedMessage.new(
|
42
|
+
received_method_name, *received_arguments, &received_block
|
43
|
+
)
|
44
|
+
received_messages.#{sprintf(core_definition, 'received_message')}
|
45
|
+
end
|
23
46
|
end
|
47
|
+
END
|
48
|
+
end
|
49
|
+
|
50
|
+
def prepend_features klass
|
51
|
+
super
|
52
|
+
|
53
|
+
without_black_listed_methods(klass.public_instance_methods).each do|method_name|
|
54
|
+
self.module_eval { define_wrapper(method_name) }
|
55
|
+
end
|
56
|
+
klass.protected_instance_methods.each do|method_name|
|
57
|
+
self.module_eval { protected define_wrapper(method_name) }
|
58
|
+
end
|
59
|
+
klass.private_instance_methods.each do|method_name|
|
60
|
+
self.module_eval { private define_wrapper(method_name) }
|
24
61
|
end
|
25
62
|
end
|
63
|
+
private :prepend_features
|
64
|
+
|
65
|
+
def without_black_listed_methods method_names
|
66
|
+
method_names.reject {|method_name| BLACK_LISTED_METHODS.include? method_name }
|
67
|
+
end
|
68
|
+
private :without_black_listed_methods
|
69
|
+
|
70
|
+
def initialize_spy
|
71
|
+
@spying = true
|
72
|
+
end
|
73
|
+
private :initialize_spy
|
26
74
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
else
|
31
|
-
@received_messages.count ::Crispy::Crispy::ReceivedMessage.new(method_name, *arguments, &attached_block)
|
75
|
+
def assert_symbol! maybe_symbol
|
76
|
+
unless maybe_symbol.respond_to?(:to_sym) && maybe_symbol.to_sym.instance_of?(::Symbol)
|
77
|
+
raise TypeError, "TypeError: no implicit conversion from #{maybe_symbol.inspect} to symbol"
|
32
78
|
end
|
33
79
|
end
|
34
80
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Crispy
|
2
|
+
class CrispyReceivedMessage
|
3
|
+
|
4
|
+
DELEGATABLE_METHODS = [:method_name, :arguments, :attached_block]
|
5
|
+
|
6
|
+
attr_reader(*DELEGATABLE_METHODS)
|
7
|
+
|
8
|
+
class << self
|
9
|
+
alias [] new
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize method_name, *arguments, &attached_block
|
13
|
+
@method_name = method_name
|
14
|
+
@arguments = arguments
|
15
|
+
@attached_block = attached_block
|
16
|
+
end
|
17
|
+
|
18
|
+
def == other
|
19
|
+
@method_name == other.method_name &&
|
20
|
+
@arguments == other.arguments &&
|
21
|
+
@attached_block == other.attached_block
|
22
|
+
end
|
23
|
+
|
24
|
+
CLASS_NAME = self.name
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"#<#{CLASS_NAME}[#{(@method_name).inspect}, *#{@arguments.inspect}]>"
|
28
|
+
end
|
29
|
+
|
30
|
+
alias inspect to_s
|
31
|
+
|
32
|
+
PP_HEADER = "#<#{CLASS_NAME}["
|
33
|
+
|
34
|
+
def pretty_print pp
|
35
|
+
pp.group 2, PP_HEADER do
|
36
|
+
pp.pp @method_name
|
37
|
+
pp.text ','.freeze
|
38
|
+
pp.breakable
|
39
|
+
pp.text '*'.freeze
|
40
|
+
pp.pp @arguments
|
41
|
+
pp.text ']>'.freeze
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
PP_CYCLE = "#{PP_HEADER}...]>"
|
46
|
+
|
47
|
+
def pretty_print_cycle pp
|
48
|
+
pp.text PP_CYCLE
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'crispy/crispy_received_message'
|
2
|
+
|
3
|
+
module Crispy
|
4
|
+
class CrispyReceivedMessageWithReceiver
|
5
|
+
attr_reader :receiver, :received_message
|
6
|
+
|
7
|
+
class << self
|
8
|
+
alias [] new
|
9
|
+
end
|
10
|
+
|
11
|
+
CrispyReceivedMessage::DELEGATABLE_METHODS.each do|method_name|
|
12
|
+
binding.eval(<<-END, __FILE__, (__LINE__ + 1))
|
13
|
+
def #{method_name}
|
14
|
+
@received_message.#{method_name}
|
15
|
+
end
|
16
|
+
END
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize receiver, method_name, *arguments, &attached_block
|
20
|
+
@received_message = CrispyReceivedMessage.new(method_name, *arguments, &attached_block)
|
21
|
+
@receiver = receiver
|
22
|
+
end
|
23
|
+
|
24
|
+
def == other
|
25
|
+
@receiver == other.receiver && @received_message == other.received_message
|
26
|
+
end
|
27
|
+
|
28
|
+
CLASS_NAME = self.name
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"#<#{CLASS_NAME}[#{@receiver.inspect}, #{(@received_message.method_name).inspect}, *#{@received_message.arguments.inspect}]>"
|
32
|
+
end
|
33
|
+
|
34
|
+
alias inspect to_s
|
35
|
+
|
36
|
+
PP_HEADER = "#<#{CLASS_NAME}["
|
37
|
+
|
38
|
+
def pretty_print pp
|
39
|
+
pp.group 2, PP_HEADER do
|
40
|
+
pp.pp @receiver
|
41
|
+
pp.text ','.freeze
|
42
|
+
pp.breakable
|
43
|
+
|
44
|
+
pp.pp @received_message.method_name
|
45
|
+
pp.text ','.freeze
|
46
|
+
pp.breakable
|
47
|
+
|
48
|
+
pp.text '*'.freeze
|
49
|
+
pp.pp @received_message.arguments
|
50
|
+
pp.text ']>'.freeze
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
PP_CYCLE = "#{PP_HEADER}...]>"
|
55
|
+
|
56
|
+
def pretty_print_cycle pp
|
57
|
+
pp.text PP_CYCLE
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/lib/crispy/version.rb
CHANGED
data/lib/crispy.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "crispy/version"
|
2
2
|
require "crispy/crispy_internal/spy"
|
3
|
+
require "crispy/crispy_internal/class_spy"
|
3
4
|
require "crispy/crispy_internal/double"
|
5
|
+
require "crispy/crispy_world"
|
4
6
|
|
5
7
|
module Crispy
|
6
8
|
# All methods of this module should be module_function.
|
@@ -16,8 +18,7 @@ module Crispy
|
|
16
18
|
end
|
17
19
|
|
18
20
|
# Make and returns a Crispy::ClassSpy's instance to spy all instances of a class.
|
19
|
-
def
|
20
|
-
raise NotImplementedError, "Sorry, this feature is under construction :("
|
21
|
+
def spy_into_instances klass#, stubs_map = {}
|
21
22
|
::Crispy::CrispyInternal::ClassSpy.new klass
|
22
23
|
end
|
23
24
|
|
@@ -25,17 +26,13 @@ module Crispy
|
|
25
26
|
object.__CRISPY_SPY__
|
26
27
|
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
def spy_into_class! klass
|
31
|
-
raise NotImplementedError, "Sorry, this feature is under construction :("
|
32
|
-
spy_class = spy_on_any_instance_of klass
|
33
|
-
stub_const! klass.name, spy_class
|
34
|
-
spy_class
|
29
|
+
def spy_of_instances klass
|
30
|
+
::Crispy::CrispyInternal::ClassSpy.of_class(klass)
|
35
31
|
end
|
36
32
|
|
37
|
-
def stub_const
|
38
|
-
|
33
|
+
def stub_const full_const_name, value
|
34
|
+
saved_value = ::Crispy::CrispyInternal::ConstChanger.change_by_full_name full_const_name, value
|
35
|
+
::Crispy::CrispyInternal::ConstChanger.save full_const_name, saved_value
|
39
36
|
end
|
40
37
|
|
41
38
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class YourCoolClass
|
2
|
+
YOUR_COOL_CONST = 'value before stubbed'.freeze
|
2
3
|
def your_cool_method *args
|
3
4
|
end
|
4
5
|
def your_method_without_argument
|
@@ -7,4 +8,11 @@ class YourCoolClass
|
|
7
8
|
end
|
8
9
|
def your_finalizer *args
|
9
10
|
end
|
11
|
+
|
12
|
+
class Again < self
|
13
|
+
def your_another_method *args
|
14
|
+
end
|
15
|
+
def some_method_for_testing
|
16
|
+
end
|
17
|
+
end
|
10
18
|
end
|
data/test/test_crispy.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
$VERBOSE = true # enable warnings
|
2
2
|
|
3
3
|
require 'crispy'
|
4
|
+
require_relative 'test_helper'
|
4
5
|
require 'minitest/autorun'
|
5
6
|
|
6
7
|
class TestCrispy < MiniTest::Test
|
@@ -8,6 +9,9 @@ class TestCrispy < MiniTest::Test
|
|
8
9
|
|
9
10
|
# Inherit BasicObject because it has fewer meta-programming methods than Object
|
10
11
|
class ObjectClass < BasicObject
|
12
|
+
|
13
|
+
CONSTANT_TO_STUB = ::Crispy.double('value_before_stubbed')
|
14
|
+
|
11
15
|
def hoge a, b, c
|
12
16
|
private_foo a
|
13
17
|
[a, b, c]
|
@@ -18,6 +22,8 @@ class TestCrispy < MiniTest::Test
|
|
18
22
|
def bar
|
19
23
|
[]
|
20
24
|
end
|
25
|
+
def baz
|
26
|
+
end
|
21
27
|
def method_to_stub1
|
22
28
|
fail "Not stubbed actually! The test fails."
|
23
29
|
end
|
@@ -32,6 +38,25 @@ class TestCrispy < MiniTest::Test
|
|
32
38
|
|
33
39
|
end
|
34
40
|
|
41
|
+
class TestCrispyStubConst < TestCrispy
|
42
|
+
|
43
|
+
def setup
|
44
|
+
@saved_value = ::TestCrispy::ObjectClass::CONSTANT_TO_STUB
|
45
|
+
@stubbbed_value = double('value_after_stubbed')
|
46
|
+
stub_const '::TestCrispy::ObjectClass::CONSTANT_TO_STUB', @stubbbed_value
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_stubbed_const_value_changes_into_2nd_argument_value
|
50
|
+
assert_same @stubbbed_value, ::TestCrispy::ObjectClass::CONSTANT_TO_STUB
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_stubbed_const_value_changes_back_after_resetting
|
54
|
+
CrispyWorld.reset
|
55
|
+
assert_same @saved_value, ::TestCrispy::ObjectClass::CONSTANT_TO_STUB
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
35
60
|
class TestCrispySpyInto < TestCrispy
|
36
61
|
|
37
62
|
def setup
|
@@ -51,11 +76,11 @@ class TestCrispy < MiniTest::Test
|
|
51
76
|
def test_spy_logs_messages_sent_to_an_object
|
52
77
|
assert_equal(
|
53
78
|
[
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
79
|
+
CrispyReceivedMessage[:hoge, 1, 2, 3],
|
80
|
+
CrispyReceivedMessage[:private_foo, 1],
|
81
|
+
CrispyReceivedMessage[:foo],
|
82
|
+
CrispyReceivedMessage[:hoge, 3, 4, 5],
|
83
|
+
CrispyReceivedMessage[:private_foo, 3],
|
59
84
|
],
|
60
85
|
@subject.received_messages
|
61
86
|
)
|
@@ -113,6 +138,311 @@ class TestCrispy < MiniTest::Test
|
|
113
138
|
assert_same @subject, @returned_spy
|
114
139
|
end
|
115
140
|
|
141
|
+
def test_spy_raises_error_given_non_symbol_as_method_name
|
142
|
+
assert_raises(::TypeError){ @subject.received_once?(nil) }
|
143
|
+
assert_raises(::TypeError){ @subject.received_once?(nil) }
|
144
|
+
assert_raises(::TypeError){ @subject.count_received(nil) }
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
class TestCrispySpyIntoInstances < TestCrispy
|
150
|
+
|
151
|
+
def object_class
|
152
|
+
raise NotImplementedError
|
153
|
+
end
|
154
|
+
|
155
|
+
def setup
|
156
|
+
@returned_spy = spy_into_instances(
|
157
|
+
object_class#, method_to_stub1: :stubbed_instance_method1, method_to_stub2: :stubbed_instance_method2
|
158
|
+
)
|
159
|
+
|
160
|
+
@subject = spy_of_instances(object_class)
|
161
|
+
@object_instances = Array.new(3){ object_class.new }
|
162
|
+
|
163
|
+
@object_instances[0].hoge 3, 4, 5
|
164
|
+
@object_instances[1].hoge 1, 2, 3
|
165
|
+
@object_instances[0].foo
|
166
|
+
@object_instances[2].hoge 3, 4, 5
|
167
|
+
@object_instances[1].bar
|
168
|
+
@object_instances[2].hoge 7, 8, 9
|
169
|
+
@object_instances[1].bar
|
170
|
+
end
|
171
|
+
|
172
|
+
def teardown
|
173
|
+
CrispyWorld.reset
|
174
|
+
end
|
175
|
+
|
176
|
+
class TestReceivedMessage < self
|
177
|
+
|
178
|
+
def object_class
|
179
|
+
ObjectClass
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_spy_logs_messages_sent_to_instances_of_a_class
|
183
|
+
assert_equal(
|
184
|
+
[
|
185
|
+
CrispyReceivedMessage[:initialize],
|
186
|
+
CrispyReceivedMessage[:initialize],
|
187
|
+
CrispyReceivedMessage[:initialize],
|
188
|
+
CrispyReceivedMessage[:hoge, 3, 4, 5],
|
189
|
+
CrispyReceivedMessage[:private_foo, 3],
|
190
|
+
CrispyReceivedMessage[:hoge, 1, 2, 3],
|
191
|
+
CrispyReceivedMessage[:private_foo, 1],
|
192
|
+
CrispyReceivedMessage[:foo],
|
193
|
+
CrispyReceivedMessage[:hoge, 3, 4, 5],
|
194
|
+
CrispyReceivedMessage[:private_foo, 3],
|
195
|
+
CrispyReceivedMessage[:bar],
|
196
|
+
CrispyReceivedMessage[:hoge, 7, 8, 9],
|
197
|
+
CrispyReceivedMessage[:private_foo, 7],
|
198
|
+
CrispyReceivedMessage[:bar],
|
199
|
+
],
|
200
|
+
@subject.received_messages_with_receiver
|
201
|
+
)
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_spy_has_received_messages_sent_to_an_object
|
205
|
+
assert @subject.received?(:hoge)
|
206
|
+
assert @subject.received?(:foo)
|
207
|
+
assert not(@subject.received?(:baz))
|
208
|
+
assert @subject.received?(:private_foo)
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_spy_has_received_messages_with_arguments_sent_to_an_object
|
212
|
+
assert @subject.received?(:hoge, 1, 2, 3)
|
213
|
+
assert @subject.received?(:hoge, 3, 4, 5)
|
214
|
+
assert @subject.received?(:private_foo, 1)
|
215
|
+
assert @subject.received?(:private_foo, 3)
|
216
|
+
assert not(@subject.received?(:hoge, 0, 0, 0))
|
217
|
+
assert not(@subject.received?(:private_foo, 0, 0, 0))
|
218
|
+
assert not(@subject.received?(:foo, 1))
|
219
|
+
assert not(@subject.received?(:bar, nil))
|
220
|
+
assert not(@subject.received?(:baz, nil))
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_spy_has_received_messages_once_sent_to_an_object
|
224
|
+
assert not(@subject.received_once?(:hoge))
|
225
|
+
assert not(@subject.received_once?(:private_foo))
|
226
|
+
assert not(@subject.received_once?(:hoge, 3, 4, 5))
|
227
|
+
assert not(@subject.received_once?(:private_foo, 3))
|
228
|
+
assert not(@subject.received_once?(:private_foo, 3, 4))
|
229
|
+
assert @subject.received_once?(:foo)
|
230
|
+
assert not(@subject.received_once?(:bar))
|
231
|
+
assert not(@subject.received_once?(:baz))
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_spy_counts_received_messages_sent_to_an_object
|
235
|
+
assert_equal(1, @subject.count_received(:hoge, 1, 2, 3))
|
236
|
+
assert_equal(2, @subject.count_received(:hoge, 3, 4, 5))
|
237
|
+
assert_equal(0, @subject.count_received(:hoge, 0, 0, 0))
|
238
|
+
assert_equal(4, @subject.count_received(:hoge))
|
239
|
+
|
240
|
+
assert_equal(1, @subject.count_received(:private_foo, 1))
|
241
|
+
assert_equal(2, @subject.count_received(:private_foo, 3))
|
242
|
+
assert_equal(0, @subject.count_received(:private_foo, 0))
|
243
|
+
assert_equal(4, @subject.count_received(:private_foo))
|
244
|
+
|
245
|
+
assert_equal(1, @subject.count_received(:foo))
|
246
|
+
assert_equal(2, @subject.count_received(:bar))
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_spy_raises_error_given_non_symbol_as_method_name
|
250
|
+
assert_raises(::TypeError){ @subject.received_once?(nil) }
|
251
|
+
assert_raises(::TypeError){ @subject.received_once?(nil) }
|
252
|
+
assert_raises(::TypeError){ @subject.count_received(nil) }
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
class TestReceivedMessageWithReceiver < self
|
258
|
+
|
259
|
+
def object_class
|
260
|
+
ObjectClassNonBasic
|
261
|
+
end
|
262
|
+
|
263
|
+
class ObjectClassNonBasic
|
264
|
+
|
265
|
+
def hoge a, b, c
|
266
|
+
private_foo a
|
267
|
+
[a, b, c]
|
268
|
+
end
|
269
|
+
def foo
|
270
|
+
123
|
271
|
+
end
|
272
|
+
def bar
|
273
|
+
[]
|
274
|
+
end
|
275
|
+
def baz
|
276
|
+
end
|
277
|
+
def method_to_stub1
|
278
|
+
fail "Not stubbed actually! The test fails."
|
279
|
+
end
|
280
|
+
def method_to_stub2
|
281
|
+
fail "Not stubbed actually! The test fails."
|
282
|
+
end
|
283
|
+
|
284
|
+
def private_foo a
|
285
|
+
:private_foo
|
286
|
+
end
|
287
|
+
private :private_foo
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_spy_logs_messages_with_receiver_sent_to_instances_of_a_class
|
292
|
+
assert_equal(
|
293
|
+
[
|
294
|
+
CrispyReceivedMessageWithReceiver[@object_instances[0], :initialize],
|
295
|
+
CrispyReceivedMessageWithReceiver[@object_instances[1], :initialize],
|
296
|
+
CrispyReceivedMessageWithReceiver[@object_instances[2], :initialize],
|
297
|
+
CrispyReceivedMessageWithReceiver[@object_instances[0], :hoge, 3, 4, 5],
|
298
|
+
CrispyReceivedMessageWithReceiver[@object_instances[0], :private_foo, 3],
|
299
|
+
CrispyReceivedMessageWithReceiver[@object_instances[1], :hoge, 1, 2, 3],
|
300
|
+
CrispyReceivedMessageWithReceiver[@object_instances[1], :private_foo, 1],
|
301
|
+
CrispyReceivedMessageWithReceiver[@object_instances[0], :foo],
|
302
|
+
CrispyReceivedMessageWithReceiver[@object_instances[2], :hoge, 3, 4, 5],
|
303
|
+
CrispyReceivedMessageWithReceiver[@object_instances[2], :private_foo, 3],
|
304
|
+
CrispyReceivedMessageWithReceiver[@object_instances[1], :bar],
|
305
|
+
CrispyReceivedMessageWithReceiver[@object_instances[2], :hoge, 7, 8, 9],
|
306
|
+
CrispyReceivedMessageWithReceiver[@object_instances[2], :private_foo, 7],
|
307
|
+
CrispyReceivedMessageWithReceiver[@object_instances[1], :bar],
|
308
|
+
],
|
309
|
+
@subject.received_messages_with_receiver
|
310
|
+
)
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_spy_has_received_messages_with_receiver_sent_to_an_object
|
314
|
+
assert @subject.received_with_receiver?(@object_instances[0], :hoge)
|
315
|
+
assert @subject.received_with_receiver?(@object_instances[0], :foo)
|
316
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :baz))
|
317
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :bar))
|
318
|
+
assert @subject.received_with_receiver?(@object_instances[0], :private_foo)
|
319
|
+
|
320
|
+
assert @subject.received_with_receiver?(@object_instances[1], :hoge)
|
321
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :foo))
|
322
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :baz))
|
323
|
+
assert @subject.received_with_receiver?(@object_instances[1], :bar)
|
324
|
+
assert @subject.received_with_receiver?(@object_instances[1], :private_foo)
|
325
|
+
|
326
|
+
assert @subject.received_with_receiver?(@object_instances[2], :hoge)
|
327
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :foo))
|
328
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :baz))
|
329
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :bar))
|
330
|
+
assert @subject.received_with_receiver?(@object_instances[2], :private_foo)
|
331
|
+
end
|
332
|
+
|
333
|
+
def test_spy_has_received_messages_with_receiver_and_arguments_sent_to_an_object
|
334
|
+
assert @subject.received_with_receiver?(@object_instances[0], :hoge, 3, 4, 5)
|
335
|
+
assert @subject.received_with_receiver?(@object_instances[0], :private_foo, 3)
|
336
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :hoge, 1, 2, 3))
|
337
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :private_foo, 1))
|
338
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :foo, 1))
|
339
|
+
assert not(@subject.received_with_receiver?(@object_instances[0], :bar, nil))
|
340
|
+
|
341
|
+
assert @subject.received_with_receiver?(@object_instances[1], :hoge, 1, 2, 3)
|
342
|
+
assert @subject.received_with_receiver?(@object_instances[1], :private_foo, 1)
|
343
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :hoge, 0, 0, 0))
|
344
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :private_foo, 0, 0, 0))
|
345
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :hoge, 3, 4, 5))
|
346
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :private_foo, 3))
|
347
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :foo, 1))
|
348
|
+
assert not(@subject.received_with_receiver?(@object_instances[1], :baz, nil))
|
349
|
+
|
350
|
+
assert @subject.received_with_receiver?(@object_instances[2], :hoge, 7, 8, 9)
|
351
|
+
assert @subject.received_with_receiver?(@object_instances[2], :private_foo, 7)
|
352
|
+
assert @subject.received_with_receiver?(@object_instances[2], :hoge, 3, 4, 5)
|
353
|
+
assert @subject.received_with_receiver?(@object_instances[2], :private_foo, 3)
|
354
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :hoge, 1, 2, 3))
|
355
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :private_foo, 1))
|
356
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :hoge, 0, 0, 0))
|
357
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :private_foo, 0, 0, 0))
|
358
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :foo, 1))
|
359
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :bar, nil))
|
360
|
+
assert not(@subject.received_with_receiver?(@object_instances[2], :baz, nil))
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_spy_has_received_messages_with_receiver_once_sent_to_an_object
|
364
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :hoge)
|
365
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :private_foo)
|
366
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :hoge, 3, 4, 5)
|
367
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :private_foo, 3)
|
368
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[0], :hoge, 1, 2, 3))
|
369
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[0], :private_foo, 1))
|
370
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[0], :private_foo, 3, 4))
|
371
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :foo)
|
372
|
+
assert @subject.received_once_with_receiver?(@object_instances[0], :initialize)
|
373
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[0], :bar))
|
374
|
+
|
375
|
+
assert @subject.received_once_with_receiver?(@object_instances[1], :hoge)
|
376
|
+
assert @subject.received_once_with_receiver?(@object_instances[1], :private_foo)
|
377
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :hoge, 3, 4, 5))
|
378
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :private_foo, 3))
|
379
|
+
assert @subject.received_once_with_receiver?(@object_instances[1], :hoge, 1, 2, 3)
|
380
|
+
assert @subject.received_once_with_receiver?(@object_instances[1], :private_foo, 1)
|
381
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :private_foo, 1, 2))
|
382
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :foo))
|
383
|
+
assert @subject.received_once_with_receiver?(@object_instances[1], :initialize)
|
384
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :bar))
|
385
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[1], :baz))
|
386
|
+
|
387
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :hoge))
|
388
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :private_foo))
|
389
|
+
assert @subject.received_once_with_receiver?(@object_instances[2], :hoge, 7, 8, 9)
|
390
|
+
assert @subject.received_once_with_receiver?(@object_instances[2], :private_foo, 7)
|
391
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :hoge, 1, 2, 3))
|
392
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :private_foo, 1))
|
393
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :private_foo, 1, 2))
|
394
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :foo))
|
395
|
+
assert @subject.received_once_with_receiver?(@object_instances[2], :initialize)
|
396
|
+
assert not(@subject.received_once_with_receiver?(@object_instances[2], :baz))
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_spy_counts_received_with_receiver_messages_with_receiver_sent_to_an_object
|
400
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :initialize))
|
401
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[0], :initialize, 0))
|
402
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :hoge))
|
403
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :hoge, 3, 4, 5))
|
404
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[0], :hoge, 1, 2, 3))
|
405
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :private_foo))
|
406
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :private_foo, 3))
|
407
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[0], :private_foo, 1))
|
408
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[0], :foo))
|
409
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[0], :bar))
|
410
|
+
|
411
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[1], :initialize))
|
412
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[1], :initialize, 1))
|
413
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[1], :hoge))
|
414
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[1], :hoge, 1, 2, 3))
|
415
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[1], :hoge, 3, 4, 5))
|
416
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[1], :private_foo))
|
417
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[1], :private_foo, 1))
|
418
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[1], :private_foo, 3))
|
419
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[1], :foo))
|
420
|
+
assert_equal(2, @subject.count_received_with_receiver(@object_instances[1], :bar))
|
421
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[1], :bar, 9))
|
422
|
+
|
423
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[2], :initialize))
|
424
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :initialize, 2))
|
425
|
+
assert_equal(2, @subject.count_received_with_receiver(@object_instances[2], :hoge))
|
426
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[2], :hoge, 3, 4, 5))
|
427
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[2], :hoge, 7, 8, 9))
|
428
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :hoge, 1, 2, 3))
|
429
|
+
assert_equal(2, @subject.count_received_with_receiver(@object_instances[2], :private_foo))
|
430
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[2], :private_foo, 3))
|
431
|
+
assert_equal(1, @subject.count_received_with_receiver(@object_instances[2], :private_foo, 7))
|
432
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :private_foo, 1))
|
433
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :foo))
|
434
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :bar))
|
435
|
+
assert_equal(0, @subject.count_received_with_receiver(@object_instances[2], :baz))
|
436
|
+
end
|
437
|
+
|
438
|
+
def test_spy_raises_error_given_non_symbol_as_method_name
|
439
|
+
assert_raises(::TypeError){ @subject.received_once?(@object_instances[0], nil) }
|
440
|
+
assert_raises(::TypeError){ @subject.received_once?(@object_instances[0], nil) }
|
441
|
+
assert_raises(::TypeError){ @subject.count_received(@object_instances[0], nil) }
|
442
|
+
end
|
443
|
+
|
444
|
+
end
|
445
|
+
|
116
446
|
end
|
117
447
|
|
118
448
|
class TestCrispyDouble < TestCrispy
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crispy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yamamoto Yuji
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rubydoctest
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,7 +95,7 @@ dependencies:
|
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
description: |-
|
84
|
-
Test spy for any object
|
98
|
+
Test spy for any object.
|
85
99
|
It makes mocks obsolete so you don't have to be worried about where to put the expectations (i.e. before or after the subject method).
|
86
100
|
email:
|
87
101
|
- whosekiteneverfly@gmail.com
|
@@ -98,15 +112,20 @@ files:
|
|
98
112
|
- Rakefile
|
99
113
|
- crispy.gemspec
|
100
114
|
- lib/crispy.rb
|
101
|
-
- lib/crispy/
|
115
|
+
- lib/crispy/crispy_internal/class_spy.rb
|
116
|
+
- lib/crispy/crispy_internal/const_changer.rb
|
102
117
|
- lib/crispy/crispy_internal/double.rb
|
103
118
|
- lib/crispy/crispy_internal/spy.rb
|
104
119
|
- lib/crispy/crispy_internal/spy_mixin.rb
|
105
120
|
- lib/crispy/crispy_internal/stubber.rb
|
106
121
|
- lib/crispy/crispy_internal/with_stubber.rb
|
122
|
+
- lib/crispy/crispy_received_message.rb
|
123
|
+
- lib/crispy/crispy_received_message_with_receiver.rb
|
124
|
+
- lib/crispy/crispy_world.rb
|
107
125
|
- lib/crispy/version.rb
|
108
126
|
- test/doctest-fixtures/your_cool_class.rb
|
109
127
|
- test/test_crispy.rb
|
128
|
+
- test/test_helper.rb
|
110
129
|
homepage: https://github.com/igrep/crispy
|
111
130
|
licenses:
|
112
131
|
- MIT
|
@@ -130,7 +149,8 @@ rubyforge_project:
|
|
130
149
|
rubygems_version: 2.2.2
|
131
150
|
signing_key:
|
132
151
|
specification_version: 4
|
133
|
-
summary: Test spy for any object
|
152
|
+
summary: Test spy for any object.
|
134
153
|
test_files:
|
135
154
|
- test/doctest-fixtures/your_cool_class.rb
|
136
155
|
- test/test_crispy.rb
|
156
|
+
- test/test_helper.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Crispy
|
2
|
-
module Crispy
|
3
|
-
class ReceivedMessage
|
4
|
-
|
5
|
-
attr_reader :method_name, :arguments, :attached_block
|
6
|
-
|
7
|
-
class << self
|
8
|
-
alias [] new
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize method_name, *arguments, &attached_block
|
12
|
-
@method_name = method_name
|
13
|
-
@arguments = arguments
|
14
|
-
@attached_block = attached_block
|
15
|
-
end
|
16
|
-
|
17
|
-
def == other
|
18
|
-
@method_name == other.method_name &&
|
19
|
-
@arguments == other.arguments &&
|
20
|
-
@attached_block == other.attached_block
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|