object_mock 0.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.rdoc +97 -0
- data/lib/object_mock.rb +114 -0
- data/object_mock.gemspec +16 -0
- metadata +63 -0
data/README.rdoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
= Introduction
|
2
|
+
|
3
|
+
A group of methods added to Object class to enable simple mocking
|
4
|
+
of instance or class methods.
|
5
|
+
This mocking can be done temporarily within the scope of a block.
|
6
|
+
Alternatively it can be done indefinitely until explicitly undone.
|
7
|
+
|
8
|
+
= Object#mock
|
9
|
+
|
10
|
+
method for mocking or adding methods for a single object
|
11
|
+
(or class methods if the object is a class instance)
|
12
|
+
methods: a comma separated key value pairs
|
13
|
+
where the key is the name of the instance method to be mocked
|
14
|
+
and the value is the new definition in the form of a proc or lambda
|
15
|
+
or simply the required return for the mocked method
|
16
|
+
An optional block can passed so that the mocking is applied
|
17
|
+
only within the scope of the block
|
18
|
+
|
19
|
+
example usage:
|
20
|
+
|
21
|
+
d = Duck.new; p d.quack; p d.swim; p d.eat("fish")
|
22
|
+
# => "quack!" "swimming!" "yummy fish!!"
|
23
|
+
d.mock(:quack => "Haaahaa", :swim => "Tshhhhhhh") do
|
24
|
+
p d.quack; p d.swim
|
25
|
+
end
|
26
|
+
# => "Haaahaa" "Tshhhhhhh"
|
27
|
+
d.mock(:eat => lambda {|food| "No #{food}. Not hungry!!}) do
|
28
|
+
p d.eat("fish")
|
29
|
+
end
|
30
|
+
# => "No fish. Not hungry!!"
|
31
|
+
d.hi
|
32
|
+
# => NoMethodError: undefined method `hi'
|
33
|
+
d.mock(:hi => "Hi boss!!")
|
34
|
+
d.hi
|
35
|
+
# => "Hi boss!!"
|
36
|
+
p Duck.all; # => "quackwaaack waaack quaaaack!"
|
37
|
+
Duck.mock(:all => "Yeeeeeeeehaaaaaah")
|
38
|
+
p Duck.all
|
39
|
+
# => "Yeeeeeeeehaaaaaah"
|
40
|
+
Duck.unmock # => [:all]
|
41
|
+
p Duck.all; # => "quackwaaack waaack quaaaack!"
|
42
|
+
|
43
|
+
= Object#unmock
|
44
|
+
|
45
|
+
method for unmocking methods mocked by mock method
|
46
|
+
methods: a comma separated list of names of instance methods to be unmocked
|
47
|
+
when no methods are passed all mocked instance methods will be unmocked
|
48
|
+
returns: array of the names of methods unmocked
|
49
|
+
|
50
|
+
example usage:
|
51
|
+
|
52
|
+
d = Duck.new;
|
53
|
+
p d.quack; p d.swim # => "quack!" "swimming!"
|
54
|
+
d.mock(:quack => "Haaahaa", :swim => "Tshhhhhhh")
|
55
|
+
p d.quack; p d.swim # => "Haaahaa" "Tshhhhhhh"
|
56
|
+
d.unmock(:quack, :swim)
|
57
|
+
p d.quack; p d.swim # => "quack!" "swimming!"
|
58
|
+
|
59
|
+
= Object#class_mock
|
60
|
+
|
61
|
+
The same as mock methods but applies mocking for all instances of the class
|
62
|
+
This method can be either called on the class object or on any instance of the class
|
63
|
+
|
64
|
+
example usage:
|
65
|
+
|
66
|
+
p Duck.new.quack # => "quack!"
|
67
|
+
Duck.class_mock(:quack => "Haaahaa") do
|
68
|
+
p Duck.new.quack # => "Haaahaa"
|
69
|
+
end
|
70
|
+
p Duck.new.quack # => "quack!"
|
71
|
+
|
72
|
+
d = Duck.new
|
73
|
+
p d.swim # => "swimming!"
|
74
|
+
d.class_mock(:swim => "Tshhhhhhh") do
|
75
|
+
p Duck.new.swim; p d.swim # => "Tshhhhhhh" "Tshhhhhhh"
|
76
|
+
end
|
77
|
+
p Duck.new.swim # => "swimming!"
|
78
|
+
|
79
|
+
= Object#class_unmock
|
80
|
+
|
81
|
+
method for unmocking methods mocked using class_mock
|
82
|
+
This method can be either called on the class object or on any instance of the class
|
83
|
+
methods: a comma separated list of names of instance methods to be unmocked
|
84
|
+
when no methods are passed all mocked instance methods will be unmocked
|
85
|
+
returns: array of the names of methods unmocked
|
86
|
+
|
87
|
+
example:
|
88
|
+
|
89
|
+
d = Duck.new
|
90
|
+
p d.swim # => "swimming!"
|
91
|
+
d.class_mock(:swim => "Buckbuckbuck") do
|
92
|
+
p Duck.new.swim; p d.swim # => "Buckbuckbuck" "Buckbuckbuck"
|
93
|
+
Duck.class_unmock(:swim)
|
94
|
+
p Duck.new.swim; p d.swim # => "swimming!" "swimming!"
|
95
|
+
|
96
|
+
|
97
|
+
|
data/lib/object_mock.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# A group of methods added to Object class to enable simple mocking
|
2
|
+
# of instance or class methods.
|
3
|
+
# This mocking can be done temporarily within the scope of a block.
|
4
|
+
# Alternatively it can be done indefinitely until explicitly undone.
|
5
|
+
|
6
|
+
class Object
|
7
|
+
|
8
|
+
# method for mocking or adding methods for a single object
|
9
|
+
# (or class methods if the object is a class instance)
|
10
|
+
# methods: a comma separated key value pairs
|
11
|
+
# where the key is the name of the instance method to be mocked
|
12
|
+
# and the value is the new definition in the form of a proc or lambda
|
13
|
+
# or simply the required return for the mocked method
|
14
|
+
# An optional block can passed so that the mocking is applied
|
15
|
+
# only within the scope of the block
|
16
|
+
def mock(methods)
|
17
|
+
do_mock(methods)
|
18
|
+
if block_given?
|
19
|
+
yield
|
20
|
+
unmock(*methods.keys)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# method for unmocking methods mocked by mock method
|
25
|
+
# methods: a comma separated list of names of instance methods to be unmocked
|
26
|
+
# when no methods are passed all mocked instance methods will be unmocked
|
27
|
+
# returns: array of the names of methods unmocked
|
28
|
+
def unmock(*methods)
|
29
|
+
do_unmock(methods)
|
30
|
+
end
|
31
|
+
|
32
|
+
# The same as mock methods but applies mocking for all instances of the class
|
33
|
+
# This method can be either called on the class object or on any instance of the class
|
34
|
+
def class_mock(methods, &block)
|
35
|
+
return self.class.class_mock(methods, &block) if !self.is_a?(Module)
|
36
|
+
do_mock(methods, :instance, lambda {|m| instance_methods.collect{|n| n.to_sym}.include?(m.to_sym)}, self)
|
37
|
+
|
38
|
+
if block
|
39
|
+
block.call
|
40
|
+
class_unmock(*methods.keys)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# method for unmocking methods mocked using class_mock
|
46
|
+
# This method can be either called on the class object or on any instance of the class
|
47
|
+
# methods: a comma separated list of names of instance methods to be unmocked
|
48
|
+
# when no methods are passed all mocked instance methods will be unmocked
|
49
|
+
# returns: array of the names of methods unmocked
|
50
|
+
def class_unmock(*methods)
|
51
|
+
return self.class.class_unmock(*methods) if !self.is_a?(Module)
|
52
|
+
do_unmock(methods, :instance, self)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def do_mock(methods, type = :singleton,
|
58
|
+
exists = lambda {|m| singleton_methods.collect{|n| n.to_sym}.include?(m.to_sym)},
|
59
|
+
object = (class << self; self; end))
|
60
|
+
backup_name = "@#{type.to_s}_backup"
|
61
|
+
|
62
|
+
backup = instance_variable_get(backup_name) || {}
|
63
|
+
|
64
|
+
methods.each do |name, result|
|
65
|
+
backup[name] = backup[name] || []
|
66
|
+
|
67
|
+
if exists.call(name)
|
68
|
+
original = "#{name}_#{backup[name].length}"
|
69
|
+
object.class_eval { alias_method original, name }
|
70
|
+
elsif
|
71
|
+
original = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
backup[name] << original
|
75
|
+
t = result.respond_to?(:to_proc) ? result.to_proc : proc { result }
|
76
|
+
object.class_eval { define_method(name, t) }
|
77
|
+
end
|
78
|
+
|
79
|
+
instance_variable_set(backup_name, backup)
|
80
|
+
end
|
81
|
+
|
82
|
+
def do_unmock(methods, type = :singleton, object = (class << self; self; end))
|
83
|
+
unmocked = []
|
84
|
+
backup_name = "@#{type.to_s}_backup"
|
85
|
+
backup = instance_variable_get(backup_name)
|
86
|
+
|
87
|
+
if backup
|
88
|
+
methods = backup.keys if methods.empty?
|
89
|
+
|
90
|
+
methods.each do |name|
|
91
|
+
stack = backup[name]
|
92
|
+
if stack
|
93
|
+
if stack.last
|
94
|
+
object.class_eval do
|
95
|
+
alias_method name, stack.last
|
96
|
+
remove_method(stack.pop)
|
97
|
+
end
|
98
|
+
else
|
99
|
+
stack.pop
|
100
|
+
object.class_eval { remove_method(name) }
|
101
|
+
end
|
102
|
+
unmocked << name
|
103
|
+
backup.delete(name) if stack.empty?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
instance_eval { remove_instance_variable(backup_name) } if backup.empty?
|
108
|
+
end
|
109
|
+
|
110
|
+
return unmocked
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
data/object_mock.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "object_mock"
|
3
|
+
s.version = "0.1"
|
4
|
+
s.date = "2010-04-19"
|
5
|
+
s.summary = "A simple, flexible and reversible mocking solution"
|
6
|
+
s.email = "mohammed.shalaby@espace.com.eg"
|
7
|
+
s.homepage = "http://github.com/mshalaby/object_mock"
|
8
|
+
s.description = "A group of methods added to Object class to enable simple mocking of instance or class methods. This mocking can be done temporarily within the scope of a block. Alternatively it can be done indefinitely until explicitly undone."
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.authors = ["Mohammed Shalaby"]
|
11
|
+
s.files = [
|
12
|
+
"object_mock.gemspec",
|
13
|
+
"README.rdoc",
|
14
|
+
"lib/object_mock.rb"
|
15
|
+
]
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: object_mock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
version: "0.1"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Mohammed Shalaby
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-04-19 00:00:00 +02:00
|
17
|
+
default_executable:
|
18
|
+
dependencies: []
|
19
|
+
|
20
|
+
description: A group of methods added to Object class to enable simple mocking of instance or class methods. This mocking can be done temporarily within the scope of a block. Alternatively it can be done indefinitely until explicitly undone.
|
21
|
+
email: mohammed.shalaby@espace.com.eg
|
22
|
+
executables: []
|
23
|
+
|
24
|
+
extensions: []
|
25
|
+
|
26
|
+
extra_rdoc_files: []
|
27
|
+
|
28
|
+
files:
|
29
|
+
- object_mock.gemspec
|
30
|
+
- README.rdoc
|
31
|
+
- lib/object_mock.rb
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/mshalaby/object_mock
|
34
|
+
licenses: []
|
35
|
+
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: A simple, flexible and reversible mocking solution
|
62
|
+
test_files: []
|
63
|
+
|