object_mock 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.rdoc +97 -0
  2. data/lib/object_mock.rb +114 -0
  3. data/object_mock.gemspec +16 -0
  4. 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
+
@@ -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
+
@@ -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
+