flexmock 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG +10 -1
  2. data/README +390 -209
  3. data/Rakefile +31 -10
  4. data/doc/GoogleExample.rdoc +275 -0
  5. data/doc/releases/flexmock-0.6.0.rdoc +136 -0
  6. data/lib/flexmock.rb +3 -1160
  7. data/lib/flexmock/argument_matchers.rb +57 -0
  8. data/lib/flexmock/argument_types.rb +42 -0
  9. data/lib/flexmock/base.rb +22 -0
  10. data/lib/flexmock/composite.rb +10 -0
  11. data/lib/flexmock/core.rb +206 -0
  12. data/lib/flexmock/core_class_methods.rb +92 -0
  13. data/lib/flexmock/default_framework_adapter.rb +31 -0
  14. data/lib/flexmock/expectation.rb +334 -0
  15. data/lib/flexmock/expectation_director.rb +59 -0
  16. data/lib/flexmock/mock_container.rb +159 -0
  17. data/lib/flexmock/noop.rb +13 -0
  18. data/lib/flexmock/partial_mock.rb +226 -0
  19. data/lib/flexmock/recorder.rb +71 -0
  20. data/lib/flexmock/rspec.rb +34 -0
  21. data/lib/flexmock/test_unit.rb +32 -0
  22. data/lib/flexmock/test_unit_integration.rb +53 -0
  23. data/lib/flexmock/validators.rb +77 -0
  24. data/test/rspec_integration/integration_spec.rb +36 -0
  25. data/test/test_container_methods.rb +119 -0
  26. data/test/test_default_framework_adapter.rb +39 -0
  27. data/test/test_example.rb +1 -1
  28. data/test/test_extended_should_receive.rb +63 -0
  29. data/test/test_mock.rb +1 -1
  30. data/test/test_naming.rb +1 -1
  31. data/test/{test_any_instance.rb → test_new_instances.rb} +15 -8
  32. data/test/{test_stubbing.rb → test_partial_mock.rb} +44 -44
  33. data/test/test_record_mode.rb +1 -1
  34. data/test/test_samples.rb +6 -8
  35. data/test/test_should_receive.rb +7 -3
  36. data/test/test_tu_integration.rb +1 -1
  37. data/test/test_unit_integration/test_auto_test_unit.rb +34 -0
  38. metadata +30 -5
  39. data/test/test_class_interception.rb +0 -140
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+ #
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/noop'
13
+
14
+ class FlexMock
15
+ ####################################################################
16
+ # Match any object
17
+ class AnyMatcher
18
+ def ===(target)
19
+ true
20
+ end
21
+ def inspect
22
+ "ANY"
23
+ end
24
+ end
25
+
26
+ ####################################################################
27
+ # Match only things that are equal.
28
+ class EqualMatcher
29
+ def initialize(obj)
30
+ @obj = obj
31
+ end
32
+ def ===(target)
33
+ @obj == target
34
+ end
35
+ def inspect
36
+ "==(#{@obj.inspect})"
37
+ end
38
+ end
39
+
40
+ ANY = AnyMatcher.new
41
+
42
+ ####################################################################
43
+ # Match only things where the block evaluates to true.
44
+ class ProcMatcher
45
+ def initialize(&block)
46
+ @block = block
47
+ end
48
+ def ===(target)
49
+ @block.call(target)
50
+ end
51
+ def inspect
52
+ "on{...}"
53
+ end
54
+ end
55
+
56
+
57
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/argument_matchers'
13
+
14
+ class FlexMock
15
+
16
+ ####################################################################
17
+ # Include this module in your test class if you wish to use the +eq+
18
+ # and +any+ argument matching methods without a prefix. (Otherwise
19
+ # use <tt>FlexMock.any</tt> and <tt>FlexMock.eq(obj)</tt>.
20
+ #
21
+ module ArgumentTypes
22
+ # Return an argument matcher that matches any argument.
23
+ def any
24
+ ANY
25
+ end
26
+
27
+ # Return an argument matcher that only matches things equal to
28
+ # (==) the given object.
29
+ def eq(obj)
30
+ EqualMatcher.new(obj)
31
+ end
32
+
33
+ # Return an argument matcher that matches any object, that when
34
+ # passed to the supplied block, will cause the block to return
35
+ # true.
36
+ def on(&block)
37
+ ProcMatcher.new(&block)
38
+ end
39
+ end
40
+ extend ArgumentTypes
41
+
42
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/core'
13
+
14
+ require 'flexmock/default_framework_adapter'
15
+ require 'flexmock/expectation_director'
16
+ require 'flexmock/expectation'
17
+ require 'flexmock/argument_matchers'
18
+ require 'flexmock/argument_types'
19
+ require 'flexmock/validators'
20
+ require 'flexmock/recorder'
21
+ require 'flexmock/mock_container'
22
+ require 'flexmock/partial_mock'
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Jim Weirich on 2007-04-14.
4
+ # Copyright (c) 2007. All rights reserved.
5
+
6
+ require 'flexmock/noop'
7
+
8
+ class FlexMock
9
+
10
+ end
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+ #
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/composite'
13
+
14
+ ######################################################################
15
+ # FlexMock is a flexible mock object framework for supporting testing.
16
+ #
17
+ # FlexMock has a simple interface that's easy to remember, and leaves
18
+ # the hard stuff to all those other mock object implementations.
19
+ #
20
+ # Basic Usage:
21
+ #
22
+ # m = flexmock("name")
23
+ # m.should_receive(:upcase).with("stuff").
24
+ # and_return("STUFF")
25
+ # m.should_receive(:downcase).with(String).
26
+ # and_return { |s| s.downcase }.once
27
+ #
28
+ # With Test::Unit Integration:
29
+ #
30
+ # class TestSomething < Test::Unit::TestCase
31
+ # include FlexMock::TestCase
32
+ #
33
+ # def test_something
34
+ # m = flexmock("name")
35
+ # m.should_receive(:hi).and_return("Hello")
36
+ # m.hi
37
+ # end
38
+ # end
39
+ #
40
+ # Note: When using Test::Unit integeration, don't forget to include
41
+ # FlexMock::TestCase. Also, if you override +teardown+, make sure you
42
+ # call +super+.
43
+ #
44
+ class FlexMock
45
+ attr_reader :mock_name, :mock_groups
46
+ attr_accessor :mock_current_order, :mock_container
47
+
48
+ # Create a FlexMock object with the given name. The name is used in
49
+ # error messages.
50
+ def initialize(name="unknown")
51
+ @mock_name = name
52
+ @expectations = Hash.new
53
+ @allocated_order = 0
54
+ @mock_current_order = 0
55
+ @mock_container = nil
56
+ @mock_groups = {}
57
+ @ignore_missing = false
58
+ @verified = false
59
+ end
60
+
61
+ # Handle all messages denoted by +sym+ by calling the given block
62
+ # and passing any parameters to the block. If we know exactly how
63
+ # many calls are to be made to a particular method, we may check
64
+ # that by passing in the number of expected calls as a second
65
+ # paramter.
66
+ def mock_handle(sym, expected_count=nil, &block) # :nodoc:
67
+ self.should_receive(sym).times(expected_count).returns(&block)
68
+ end
69
+
70
+ # Verify that each method that had an explicit expected count was
71
+ # actually called that many times.
72
+ def mock_verify
73
+ return if @verified
74
+ @verified = true
75
+ mock_wrap do
76
+ @expectations.each do |sym, handler|
77
+ handler.mock_verify
78
+ end
79
+ end
80
+ end
81
+
82
+ # Teardown and infrastructure setup for this mock.
83
+ def mock_teardown
84
+ end
85
+
86
+ # Allocation a new order number from the mock.
87
+ def mock_allocate_order
88
+ @auto_allocate = true
89
+ @allocated_order += 1
90
+ end
91
+
92
+ # Ignore all undefined (missing) method calls.
93
+ def should_ignore_missing
94
+ @ignore_missing = true
95
+ end
96
+ alias mock_ignore_missing should_ignore_missing
97
+
98
+ # Handle missing methods by attempting to look up a handler.
99
+ def method_missing(sym, *args, &block)
100
+ mock_wrap do
101
+ if handler = @expectations[sym]
102
+ args << block if block_given?
103
+ handler.call(*args)
104
+ else
105
+ super(sym, *args, &block) unless @ignore_missing
106
+ end
107
+ end
108
+ end
109
+
110
+ # Save the original definition of respond_to? for use a bit later.
111
+ alias mock_respond_to? respond_to?
112
+
113
+ # Override the built-in respond_to? to include the mocked methods.
114
+ def respond_to?(sym)
115
+ super || (@expectations[sym] ? true : @ignore_missing)
116
+ end
117
+
118
+ # Override the built-in +method+ to include the mocked methods.
119
+ def method(sym)
120
+ @expectations[sym] || super
121
+ rescue NameError => ex
122
+ if @ignore_missing
123
+ proc { }
124
+ else
125
+ raise ex
126
+ end
127
+ end
128
+
129
+ # :call-seq:
130
+ # mock.should_receive(:method_name)
131
+ # mock.should_receive(:method1, method2, ...)
132
+ # mock.should_receive(:meth1 => result1, :meth2 => result2, ...)
133
+ #
134
+ # Declare that the mock object should receive a message with the given name.
135
+ #
136
+ # If more than one method name is given, then the mock object should expect
137
+ # to receive all the listed melthods. If a hash of method name/value pairs
138
+ # is given, then the each method will return the associated result. Any
139
+ # expectations applied to the result of +should_receive+ will be applied to
140
+ # all the methods defined in the argument list.
141
+ #
142
+ # An expectation object for the method name is returned as the result of
143
+ # this method. Further expectation constraints can be added by chaining to
144
+ # the result.
145
+ #
146
+ # See Expectation for a list of declarators that can be used.
147
+ #
148
+ def should_receive(*args)
149
+ FlexMock.should_receive(args) do |sym|
150
+ @expectations[sym] ||= ExpectationDirector.new(sym)
151
+ result = Expectation.new(self, sym)
152
+ @expectations[sym] << result
153
+ override_existing_method(sym) if mock_respond_to?(sym)
154
+ result
155
+ end
156
+ end
157
+
158
+ # Declare that the mock object should expect methods by providing a
159
+ # recorder for the methods and having the user invoke the expected
160
+ # methods in a block. Further expectations may be applied the
161
+ # result of the recording call.
162
+ #
163
+ # Example Usage:
164
+ #
165
+ # mock.should_expect do |record|
166
+ # record.add(Integer, 4) { |a, b|
167
+ # a + b
168
+ # }.at_least.once
169
+ #
170
+ def should_expect
171
+ yield Recorder.new(self)
172
+ end
173
+
174
+ private
175
+
176
+ # Wrap a block of code so the any assertion errors are wrapped so
177
+ # that the mock name is added to the error message .
178
+ def mock_wrap(&block)
179
+ yield
180
+ rescue FlexMock.framework_adapter.assertion_failed_error => ex
181
+ raise FlexMock.framework_adapter.assertion_failed_error,
182
+ "in mock '#{@mock_name}': #{ex.message}",
183
+ ex.backtrace
184
+ end
185
+
186
+
187
+ # Override the existing definition of method +sym+ in the mock.
188
+ # Most methods depend on the method_missing trick to be invoked.
189
+ # However, if the method already exists, it will not call
190
+ # method_missing. This method defines a singleton method on the
191
+ # mock to explicitly invoke the method_missing logic.
192
+ def override_existing_method(sym)
193
+ sclass.class_eval <<-EOS
194
+ def #{sym}(*args, &block)
195
+ method_missing(:#{sym}, *args, &block)
196
+ end
197
+ EOS
198
+ end
199
+
200
+ # Return the singleton class of the mock object.
201
+ def sclass
202
+ class << self; self; end
203
+ end
204
+ end
205
+
206
+ require 'flexmock/core_class_methods'
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/noop'
13
+
14
+ class FlexMock
15
+ class << self
16
+ attr_reader :framework_adapter
17
+
18
+ # :call-seq:
19
+ # should_receive(args) { |symbol| ... }
20
+ #
21
+ # This method provides common handling for the various should_receive
22
+ # argument lists. It sorts out the differences between symbols, arrays and
23
+ # hashes, and identifies the method names specified by each. As each
24
+ # method name is identified, create a mock expectation for it using the
25
+ # supplied block.
26
+ def should_receive(args) # :nodoc:
27
+ result = CompositeExpectation.new
28
+ args.each do |arg|
29
+ case arg
30
+ when Hash
31
+ arg.each do |k,v|
32
+ result.add(yield(k.to_sym).and_return(v))
33
+ end
34
+ when Symbol, String
35
+ result.add(yield(arg.to_sym))
36
+ end
37
+ end
38
+ result
39
+ end
40
+
41
+ # Class method to make sure that verify is called at the end of a
42
+ # test. One mock object will be created for each name given to
43
+ # the use method. The mocks will be passed to the block as
44
+ # arguments. If no names are given, then a single anonymous mock
45
+ # object will be created.
46
+ #
47
+ # At the end of the use block, each mock object will be verified
48
+ # to make sure the proper number of calls have been made.
49
+ #
50
+ # Usage:
51
+ #
52
+ # FlexMock.use("name") do |mock| # Creates a mock named "name"
53
+ # mock.should_receive(:meth).
54
+ # returns(0).once
55
+ # end # mock is verified here
56
+ #
57
+ # NOTE: If you include FlexMock::TestCase into your test case
58
+ # file, you can create mocks that will be automatically verified in
59
+ # the test teardown by using the +flexmock+ method.
60
+ #
61
+ def use(*names)
62
+ names = ["unknown"] if names.empty?
63
+ got_excecption = false
64
+ mocks = names.collect { |n| new(n) }
65
+ yield(*mocks)
66
+ rescue Exception => ex
67
+ got_exception = true
68
+ raise
69
+ ensure
70
+ mocks.each do |mock|
71
+ mock.mock_verify unless got_exception
72
+ end
73
+ end
74
+
75
+ # Class method to format a method name and argument list as a nice
76
+ # looking string.
77
+ def format_args(sym, args) # :nodoc:
78
+ if args
79
+ "#{sym}(#{args.collect { |a| a.inspect }.join(', ')})"
80
+ else
81
+ "#{sym}(*args)"
82
+ end
83
+ end
84
+
85
+ # Check will assert the block returns true. If it doesn't, an
86
+ # assertion failure is triggered with the given message.
87
+ def check(msg, &block) # :nodoc:
88
+ FlexMock.framework_adapter.assert_block(msg, &block)
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #---
4
+ # Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #+++
11
+
12
+ require 'flexmock/noop'
13
+
14
+ class FlexMock
15
+ class DefaultFrameworkAdapter
16
+ def assert_block(msg, &block)
17
+ unless yield
18
+ fail assertion_failed_error, msg
19
+ end
20
+ end
21
+
22
+ def assert_equal(a, b, msg=nil)
23
+ assert_block(msg || "Expected equal") { a == b }
24
+ end
25
+
26
+ class AssertionFailedError < StandardError; end
27
+ def assertion_failed_error
28
+ AssertionFailedError
29
+ end
30
+ end
31
+ end