flexmock 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/CHANGELOG CHANGED
@@ -2,13 +2,23 @@
2
2
 
3
3
  = Changes for FlexMock
4
4
 
5
+ == Pre Version 0.5.1
6
+
7
+ * Changed the name of any_instance to new_instances.
8
+ Deprecated any_instance.
9
+ * Added ability to stub any class method in new_instances.
10
+ * Added RCov task
11
+ * Reworked original behavior hooks to use method aliasing rather than method
12
+ procs.
13
+ * Fixed bug in stubbing File class methods.
14
+
5
15
  == Version 0.5.0
6
16
 
7
17
  * Added any_instance stubbing to class objects.
8
18
 
9
19
  == Version 0.4.5
10
20
 
11
- * Fixed version typo in 0.4.4 (internall claimed to be 0.4.3.1)
21
+ * Fixed version typo in 0.4.4 (internally claimed to be 0.4.3.1)
12
22
 
13
23
  == Version 0.4.4
14
24
 
data/README CHANGED
@@ -3,7 +3,7 @@
3
3
  FlexMock is a simple, but flexible, mock object library for Ruby unit
4
4
  testing.
5
5
 
6
- Version :: 0.5.0
6
+ Version :: 0.5.1
7
7
 
8
8
  = Links
9
9
 
@@ -320,8 +320,8 @@ version of the object.
320
320
  <em>Class Interception is now deprecated. It only worked in a
321
321
  small number of cases. See the "Mocking Existing Objects"
322
322
  example above for a much better approach to the same problem.
323
- The Class Interception API will probably disappear in a future
324
- version of FlexMock.</em>
323
+ Version 0.5.x will be the last version of FlexMock that supports the
324
+ Class Interception API.</em>
325
325
 
326
326
  FlexMock now supports simple class interception. For the duration of a test, a
327
327
  mock class take the place of a named class inside the class to be tested.
@@ -380,7 +380,7 @@ but the third query (which matches any query call with a four
380
380
  character parameter) may be called multiple times (but at least once).
381
381
  Startup and finish must also happen exactly once.
382
382
 
383
- Also note that we use the +with+ method to match different arguement
383
+ Also note that we use the +with+ method to match different argument
384
384
  values to figure out what value to return.
385
385
 
386
386
  def test_ordered_queries
@@ -482,6 +482,7 @@ following:
482
482
  ruby-mock :: http://www.b13media.com/dev/ruby/mock.html
483
483
  test-unit-mock :: http://www.deveiate.org/code/Test-Unit-Mock.shtml
484
484
  mocha/stubba :: http://mocha.rubyforge.org/
485
+
485
486
  == License
486
487
 
487
488
  Copyright 2003, 2004, 2005, 2006 by Jim Weirich (jim@weirichhouse.org).
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ require 'rake/testtask'
9
9
  CLEAN.include('*.tmp')
10
10
  CLOBBER.include("html", 'pkg')
11
11
 
12
- PKG_VERSION = '0.5.0'
12
+ PKG_VERSION = '0.5.1'
13
13
 
14
14
  PKG_FILES = FileList[
15
15
  '[A-Z]*',
@@ -29,6 +29,7 @@ RDOC_FILES = FileList[
29
29
 
30
30
  task :default => [:test_all]
31
31
  task :test_all => [:test]
32
+ task :test_units => [:test]
32
33
  task :ta => [:test_all]
33
34
 
34
35
  # Test Targets -------------------------------------------------------
@@ -39,6 +40,23 @@ Rake::TestTask.new do |t|
39
40
  t.warning = true
40
41
  end
41
42
 
43
+ Rake::TestTask.new(:test_extended) do |t|
44
+ t.test_files = FileList['test/extended/test_*.rb']
45
+ t.verbose = true
46
+ t.verbose = true
47
+ end
48
+
49
+ # RCov Target --------------------------------------------------------
50
+
51
+ require 'rcov/rcovtask'
52
+
53
+ Rcov::RcovTask.new do |t|
54
+ t.libs << "test"
55
+ t.rcov_opts = ['-xRakefile', '-xrakefile', '-xpublish.rf', '--text-report']
56
+ t.test_files = FileList['test/test*.rb']
57
+ t.verbose = true
58
+ end
59
+
42
60
  # RDoc Target --------------------------------------------------------
43
61
 
44
62
  task :rdoc => ["README"]
@@ -0,0 +1,86 @@
1
+ = FlexMock 0.5.0 Released
2
+
3
+ FlexMock is a flexible mocking library for use in Ruby's Test::Unit
4
+ test framework. Version 0.5.1 is a minor bug fix release.
5
+
6
+ == New in 0.5.1
7
+
8
+ * Version 0.5.1 fixes a problem that caused some older versions of
9
+ RCov to core dump.
10
+
11
+ == What is FlexMock?
12
+
13
+ FlexMock is a flexible Ruby mocking library that works with Ruby's
14
+ Test::Unit framework to create easy to use mocks.
15
+
16
+ === Features
17
+
18
+ * Easy integration with Test::Unit. Mocks created with the flexmock
19
+ method are automatically verified at the end of the test.
20
+
21
+ * A fluent interface that allows mock behavior to be specified very
22
+ easily.
23
+
24
+ * A "record mode" where an existing implementation can record its
25
+ interaction with a mock for later validation against a new
26
+ implementation.
27
+
28
+ * Easy mocking of individual methods in existing, non-mock objects.
29
+
30
+ === Example
31
+
32
+ Suppose you had a Dog object that wagged a tail when it was happy.
33
+ Something like this:
34
+
35
+ class Dog
36
+ def initialize(a_tail)
37
+ @tail = a_tail
38
+ end
39
+ def happy
40
+ @tail.wag
41
+ end
42
+ end
43
+
44
+ To test the +Dog+ class without a real +Tail+ object (perhaps because
45
+ real +Tail+ objects activate servos in some robotic equipment), you
46
+ can do something like this:
47
+
48
+ require 'test/unit'
49
+ require 'flexmock'
50
+
51
+ class TestDog < Test::Unit::TestCase
52
+ include FlexMock::TestCase
53
+
54
+ def test_dog_wags_tail_when_happy
55
+ tail = flexmock("tail")
56
+ tail.should_receive(:wag).once
57
+ dog = Dog.new(tail)
58
+ dog.happy
59
+ end
60
+ end
61
+
62
+ FlexMock will automatically verify that the mocked tail object
63
+ received the message +wag+ exactly one time. If it doesn't, the test
64
+ will not pass.
65
+
66
+ See the FlexMock documentation at
67
+ http://onestepback.org/software/flexmock for details on specifying
68
+ arguments and return values on mocked methods, as well as a simple
69
+ technique for mocking tail objects when the Dog class creates the tail
70
+ objects directly.
71
+
72
+ == Availability
73
+
74
+ You can make sure you have the latest version with a quick RubyGems command:
75
+
76
+ gem install flexmock (you may need root/admin privileges)
77
+
78
+ Otherwise, you can get it from the more traditional places:
79
+
80
+ Download:: http://rubyforge.org/project/showfiles.php?group_id=170
81
+
82
+ You will find documentation at:
83
+ http://onestepback.org/software/flexmock/
84
+
85
+ -- Jim Weirich
86
+
data/lib/flexmock.rb CHANGED
@@ -66,7 +66,7 @@ class FlexMock
66
66
  @ignore_missing = false
67
67
  @verified = false
68
68
  end
69
-
69
+
70
70
  # Handle all messages denoted by +sym+ by calling the given block
71
71
  # and passing any parameters to the block. If we know exactly how
72
72
  # many calls are to be made to a particular method, we may check
@@ -155,10 +155,14 @@ class FlexMock
155
155
  # method_missing. This method defines a singleton method on the
156
156
  # mock to explicitly invoke the method_missing logic.
157
157
  def override_existing_method(sym)
158
- sclass.class_eval "def #{sym}(*args, &block) method_missing(:#{sym}, *args, &block) end"
158
+ sclass.class_eval <<-EOS
159
+ def #{sym}(*args, &block)
160
+ method_missing(:#{sym}, *args, &block)
161
+ end
162
+ EOS
159
163
  end
160
164
  private :override_existing_method
161
-
165
+
162
166
  # Return the singleton class of the mock object.
163
167
  def sclass
164
168
  class << self; self; end
@@ -208,7 +212,7 @@ class FlexMock
208
212
  #
209
213
  # NOTE: If you include FlexMock::TestCase into your test case
210
214
  # file, you can create mocks that will be automatically verified in
211
- # the test teardown by using the +flexmock+ method.
215
+ # the test teardown by using the +flexmock+ method.
212
216
  #
213
217
  def use(*names)
214
218
  names = ["unknown"] if names.empty?
@@ -223,7 +227,7 @@ class FlexMock
223
227
  mock.mock_verify unless got_exception
224
228
  end
225
229
  end
226
-
230
+
227
231
  # Class method to format a method name and argument list as a nice
228
232
  # looking string.
229
233
  def format_args(sym, args)
@@ -233,7 +237,7 @@ class FlexMock
233
237
  "#{sym}(*args)"
234
238
  end
235
239
  end
236
-
240
+
237
241
  # Check will assert the block returns true. If it doesn't, an
238
242
  # assertion failure is triggered with the given message.
239
243
  def check(msg, &block)
@@ -248,9 +252,9 @@ class FlexMock
248
252
  def mock_wrap(&block)
249
253
  yield
250
254
  rescue Test::Unit::AssertionFailedError => ex
251
- raise Test::Unit::AssertionFailedError,
252
- "in mock '#{@mock_name}': #{ex.message}",
253
- ex.backtrace
255
+ raise Test::Unit::AssertionFailedError,
256
+ "in mock '#{@mock_name}': #{ex.message}",
257
+ ex.backtrace
254
258
  end
255
259
 
256
260
  ####################################################################
@@ -297,18 +301,12 @@ class FlexMock
297
301
  # criteria.
298
302
  def call(*args)
299
303
  exp = @expectations.find { |e| e.match_args(args) && e.eligible? } ||
300
- @expectations.find { |e| e.match_args(args) } ||
301
- @expectations.find { |e| e.expected_args.nil? }
304
+ @expectations.find { |e| e.match_args(args) }
302
305
  FlexMock.check("no matching handler found for " +
303
306
  FlexMock.format_args(@sym, args)) { ! exp.nil? }
304
307
  exp.verify_call(*args)
305
308
  end
306
309
 
307
- # Same as call.
308
- def [](*args)
309
- call(*args)
310
- end
311
-
312
310
  # Append an expectation to this director.
313
311
  def <<(expectation)
314
312
  @expectations << expectation
@@ -333,7 +331,7 @@ class FlexMock
333
331
  "ANY"
334
332
  end
335
333
  end
336
-
334
+
337
335
  ####################################################################
338
336
  # Match only things that are equal.
339
337
  class EqualMatcher
@@ -347,7 +345,7 @@ class FlexMock
347
345
  "==(#{@obj.inspect})"
348
346
  end
349
347
  end
350
-
348
+
351
349
  ANY = AnyMatcher.new
352
350
 
353
351
  ####################################################################
@@ -415,8 +413,8 @@ class FlexMock
415
413
  # Validate that the method expectation was called exactly +n+
416
414
  # times.
417
415
  def validate(n)
418
- assert_equal @limit, n,
419
- "method '#{@exp}' called incorrect number of times"
416
+ assert_equal @limit, n,
417
+ "method '#{@exp}' called incorrect number of times"
420
418
  end
421
419
  end
422
420
 
@@ -428,8 +426,8 @@ class FlexMock
428
426
  # times.
429
427
  def validate(n)
430
428
  assert n >= @limit,
431
- "Method '#{@exp}' should be called at least #{@limit} times,\n" +
432
- "only called #{n} times"
429
+ "Method '#{@exp}' should be called at least #{@limit} times,\n" +
430
+ "only called #{n} times"
433
431
  end
434
432
 
435
433
  # If the expectation has been called +n+ times, is it still
@@ -448,8 +446,8 @@ class FlexMock
448
446
  # Validate the method expectation was called at least +n+ times.
449
447
  def validate(n)
450
448
  assert n <= @limit,
451
- "Method '#{@exp}' should be called at most #{@limit} times,\n" +
452
- "only called #{n} times"
449
+ "Method '#{@exp}' should be called at most #{@limit} times,\n" +
450
+ "only called #{n} times"
453
451
  end
454
452
  end
455
453
 
@@ -501,11 +499,11 @@ class FlexMock
501
499
  @count_validators.all? { |v| v.eligible?(@actual_count) }
502
500
  end
503
501
 
504
- # Validate that the order
502
+ # Validate that the order
505
503
  def validate_order
506
504
  return if @order_number.nil?
507
505
  FlexMock.check("method #{to_s} called out of order " +
508
- "(expected order #{@order_number}, was #{@mock.mock_current_order})") {
506
+ "(expected order #{@order_number}, was #{@mock.mock_current_order})") {
509
507
  @order_number >= @mock.mock_current_order
510
508
  }
511
509
  @mock.mock_current_order = @order_number
@@ -523,7 +521,9 @@ class FlexMock
523
521
  # Does the argument list match this expectation's argument
524
522
  # specification.
525
523
  def match_args(args)
526
- return false if @expected_args.nil?
524
+ # TODO: Rethink this:
525
+ # return false if @expected_args.nil?
526
+ return true if @expected_args.nil?
527
527
  return false if args.size != @expected_args.size
528
528
  (0...args.size).all? { |i| match_arg(@expected_args[i], args[i]) }
529
529
  end
@@ -531,8 +531,8 @@ class FlexMock
531
531
  # Does the expected argument match the corresponding actual value.
532
532
  def match_arg(expected, actual)
533
533
  expected === actual ||
534
- expected == actual ||
535
- ( Regexp === expected && expected === actual.to_s )
534
+ expected == actual ||
535
+ ( Regexp === expected && expected === actual.to_s )
536
536
  end
537
537
 
538
538
  # Declare that the method should expect the given argument list.
@@ -558,15 +558,15 @@ class FlexMock
558
558
  #
559
559
  # * If a single value is given, it will be returned for all matching
560
560
  # calls.
561
- # * If multiple values are given, each value will be returned in turn for
561
+ # * If multiple values are given, each value will be returned in turn for
562
562
  # each successive call. If the number of matching calls is greater
563
- # than the number of values, the last value will be returned for
563
+ # than the number of values, the last value will be returned for
564
564
  # the extra matching calls.
565
- # * If a block is given, it is evaluated on each call and its
566
- # value is returned.
567
- #
565
+ # * If a block is given, it is evaluated on each call and its
566
+ # value is returned.
567
+ #
568
568
  # For example:
569
- #
569
+ #
570
570
  # mock.should_receive(:f).returns(12) # returns 12
571
571
  #
572
572
  # mock.should_receive(:f).with(String). # returns an
@@ -575,9 +575,12 @@ class FlexMock
575
575
  # +and_return+ is an alias for +returns+.
576
576
  #
577
577
  def returns(*args, &block)
578
- @return_block = block_given? ?
579
- block :
580
- lambda { args.size == 1 ? args.first : args.shift }
578
+ @return_block =
579
+ if block_given?
580
+ block
581
+ else
582
+ lambda { args.size == 1 ? args.first : args.shift }
583
+ end
581
584
  self
582
585
  end
583
586
  alias :and_return :returns # :nodoc:
@@ -725,7 +728,7 @@ class FlexMock
725
728
  # given arguments.
726
729
  def method_missing(sym, *args, &block)
727
730
  expectation = @mock.should_receive(sym).and_return(&block)
728
- if @strict
731
+ if strict?
729
732
  args = args.collect { |arg| eq(arg) }
730
733
  expectation.with(*args).ordered.once
731
734
  else
@@ -734,7 +737,7 @@ class FlexMock
734
737
  expectation
735
738
  end
736
739
  end
737
-
740
+
738
741
  ####################################################################
739
742
  # Test::Unit::TestCase Integration.
740
743
  #
@@ -757,7 +760,7 @@ class FlexMock
757
760
  super
758
761
  flexmock_teardown
759
762
  end
760
-
763
+
761
764
  # Do the flexmock specific teardown stuff.
762
765
  def flexmock_teardown
763
766
  @flexmock_created_mocks ||= []
@@ -770,6 +773,7 @@ class FlexMock
770
773
  @flexmock_created_mocks.each do |m|
771
774
  m.mock_teardown
772
775
  end
776
+ @flexmock_created_mocks = []
773
777
  @flexmock_interceptors ||= []
774
778
  @flexmock_interceptors.each do |i|
775
779
  i.restore
@@ -788,10 +792,10 @@ class FlexMock
788
792
  flexmock_remember(mock)
789
793
  mock
790
794
  end
791
-
795
+
792
796
  # Stub the given object by overriding the behavior of individual
793
797
  # methods. The stub object returned will respond to the
794
- # +should_receive+ method, just like normal stubs.
798
+ # +should_receive+ method, just like normal stubs.
795
799
  #
796
800
  # If a block is given, then the stub object is passed to the block
797
801
  # and may be configured within the block.
@@ -815,7 +819,7 @@ class FlexMock
815
819
  yield(proxy) if block_given?
816
820
  flexmock_remember(proxy)
817
821
  end
818
-
822
+
819
823
  # Intercept the named class in the target class for the duration
820
824
  # of the test. Class interception is very simple-minded and has a
821
825
  # number of restrictions. First, the intercepted class must be
@@ -838,9 +842,9 @@ class FlexMock
838
842
  @flexmock_interceptors << result
839
843
  result
840
844
  end
841
-
845
+
842
846
  private
843
-
847
+
844
848
  def flexmock_remember(mocking_object)
845
849
  @flexmock_created_mocks ||= []
846
850
  @flexmock_created_mocks << mocking_object
@@ -868,11 +872,12 @@ class FlexMock
868
872
 
869
873
  # Intercept this class in the class to be tested.
870
874
  def intercept(intercepted_class)
875
+ self.class.show_intercept_warning
871
876
  @intercepted = intercepted_class
872
877
  update
873
878
  self
874
879
  end
875
-
880
+
876
881
  # Define the class number test that will receive the
877
882
  # interceptioned definition.
878
883
  def in(target_class)
@@ -893,16 +898,16 @@ class FlexMock
893
898
  def restore
894
899
  @proxy.proxied_class = @restore_class if @proxy
895
900
  end
896
-
901
+
897
902
  private
898
-
903
+
899
904
  # Update the interception if the definition is complete.
900
905
  def update
901
906
  if complete?
902
907
  do_interception
903
908
  end
904
909
  end
905
-
910
+
906
911
  # Is the interception definition complete. In other words, are
907
912
  # all three actors defined?
908
913
  def complete?
@@ -949,6 +954,17 @@ class FlexMock
949
954
  raise BadInterceptionError, "in #{where} class #{name}"
950
955
  end
951
956
  end
957
+
958
+ @shown_warning = false
959
+
960
+ class << self
961
+ def show_intercept_warning
962
+ unless @shown_warning
963
+ @shown_warning = true
964
+ $stderr.puts "FlexMock Class Interception is deprecated and will be removed in future versions."
965
+ end
966
+ end
967
+ end
952
968
  end
953
969
 
954
970
  ####################################################################
@@ -964,21 +980,21 @@ class FlexMock
964
980
  @proxied_class.__send__(sym, *args, &block)
965
981
  end
966
982
  end
967
-
983
+
968
984
  ####################################################################
969
985
  # StubProxy is used to mate the mock framework to an existing
970
986
  # object. The object is "enhanced" with a reference to a mock
971
- # object (stored in <tt>@flexmock_mock</tt>). When the
972
- # +should_receive+ method is sent to the proxy, it overrides the
973
- # existing object's method by creating singleton method that
987
+ # object (stored in <tt>@flexmock_mock</tt>). When the
988
+ # +should_receive+ method is sent to the proxy, it overrides the
989
+ # existing object's method by creating singleton method that
974
990
  # forwards to the mock. When testing is complete, StubProxy
975
- # will erase the mocking infrastructure from the object being
976
- # stubbed (e.g. remove instance variables and mock singleton
991
+ # will erase the mocking infrastructure from the object being
992
+ # stubbed (e.g. remove instance variables and mock singleton
977
993
  # methods).
978
994
  #
979
995
  class StubProxy
980
996
  attr_reader :mock
981
-
997
+
982
998
  # Initialize a StubProxy object.
983
999
  def initialize(obj, mock)
984
1000
  @obj = obj
@@ -986,8 +1002,8 @@ class FlexMock
986
1002
  @method_definitions = {}
987
1003
  @methods_proxied = []
988
1004
  end
989
-
990
- # Stub out the given method in the existing object and then let the
1005
+
1006
+ # Stub out the given method in the existing object and then let the
991
1007
  # mock object handle should_receive.
992
1008
  def should_receive(method_name)
993
1009
  method_name = method_name.to_sym
@@ -997,34 +1013,52 @@ class FlexMock
997
1013
  end
998
1014
  @mock.should_receive(method_name)
999
1015
  end
1000
-
1001
- # any_instance is a short cut method for overriding the behavior of any
1002
- # instance created via a stubbed class object.
1003
- def any_instance(&block)
1004
- fail ArgumentError, "any_instance requires a Class to stub" unless Class === @obj
1005
- self.should_receive(:new).and_return { |*args|
1006
- new_obj = invoke_original(:new, args)
1007
- mock = mock_container.flexstub(new_obj)
1008
- block.call(mock)
1009
- new_obj
1010
- }
1016
+
1017
+ # new_instances is a short cut method for overriding the behavior of any
1018
+ # new instances created via a stubbed class object.
1019
+ #
1020
+ # By default, new_instances will stub the behaviour of the :new and
1021
+ # :allocate methods. If you wish to stub a different set of class
1022
+ # methods, just pass a list of symbols to as arguments.
1023
+ #
1024
+ # For example, to stub only objects created by :make (and not :new
1025
+ # or :allocate), use:
1026
+ #
1027
+ # flexstub(ClassName).new_instances(:make) do |obj|
1028
+ # obj.should_receive(...)
1029
+ # end
1030
+ #
1031
+ def new_instances(*allocators, &block)
1032
+ fail ArgumentError, "new_instances requires a Class to stub" unless Class === @obj
1033
+ fail ArgumentError, "new_instances requires a block" unless block_given?
1034
+ allocators = [:new, :allocate] if allocators.empty?
1035
+ allocators.each do |m|
1036
+ self.should_receive(m).and_return { |*args|
1037
+ new_obj = invoke_original(m, args)
1038
+ mock = mock_container.flexstub(new_obj)
1039
+ block.call(mock)
1040
+ new_obj
1041
+ }
1042
+ end
1011
1043
  nil
1012
1044
  end
1013
1045
 
1014
- # Invoke the original definition of method on the object supported by
1046
+ # any_instance is present for backwards compatibility with version 0.5.0.
1047
+ # @deprecated
1048
+ def any_instance(&block)
1049
+ $stderr.puts "any_instance is deprecated, use new_instances instead."
1050
+ new_instances(&block)
1051
+ end
1052
+
1053
+ # Invoke the original definition of method on the object supported by
1015
1054
  # the stub.
1016
1055
  def invoke_original(method, args)
1017
- method_proc = @method_definitions[:new]
1018
- block = nil
1019
- if Proc === args.last
1020
- block = args.last
1021
- args = args[0...-1]
1022
- end
1023
- method_proc.call(*args, &block)
1056
+ method_proc = @method_definitions[method]
1057
+ method_proc.call(*args)
1024
1058
  end
1025
1059
  private :invoke_original
1026
1060
 
1027
- # Verify that the mock has been properly called. After verification,
1061
+ # Verify that the mock has been properly called. After verification,
1028
1062
  # detach the mocking infrastructure from the existing object.
1029
1063
  def mock_verify
1030
1064
  @mock.mock_verify
@@ -1041,14 +1075,14 @@ class FlexMock
1041
1075
  @obj = nil
1042
1076
  end
1043
1077
  end
1044
-
1045
- # Return the container for this mocking object. Returns nil if the
1078
+
1079
+ # Return the container for this mocking object. Returns nil if the
1046
1080
  # mock is not in a container. Mock containers make sure that mock objects
1047
1081
  # inside the container are torn down at the end of a test
1048
1082
  def mock_container
1049
1083
  @mock.mock_container
1050
1084
  end
1051
-
1085
+
1052
1086
  # Set the container for this mock object.
1053
1087
  def mock_container=(container)
1054
1088
  @mock.mock_container = container
@@ -1074,7 +1108,23 @@ class FlexMock
1074
1108
  # not a singleton, all we need to do is override it with our own
1075
1109
  # singleton.
1076
1110
  def hide_existing_method(method_name)
1077
- @method_definitions[method_name] = @obj.method(method_name) if @obj.respond_to?(method_name)
1111
+ if @obj.respond_to?(method_name)
1112
+ new_alias = new_name(method_name)
1113
+ unless @obj.respond_to?(new_alias)
1114
+ sclass.class_eval do
1115
+ alias_method(new_alias, method_name)
1116
+ end
1117
+ end
1118
+ my_object = @obj
1119
+ @method_definitions[method_name] = Proc.new { |*args|
1120
+ block = nil
1121
+ if Proc === args.last
1122
+ block = args.last
1123
+ args = args[0...-1]
1124
+ end
1125
+ my_object.send(new_alias, *args, &block)
1126
+ }
1127
+ end
1078
1128
  remove_current_method(method_name) if singleton?(method_name)
1079
1129
  define_proxy_method(method_name)
1080
1130
  end
@@ -1084,9 +1134,7 @@ class FlexMock
1084
1134
  # being mocked.
1085
1135
  def define_proxy_method(method_name)
1086
1136
  sclass.class_eval %{
1087
- def #{method_name}(*args, &block)
1088
- @flexmock_proxy.mock.#{method_name}(*args, &block)
1089
- end
1137
+ def #{method_name}(*args, &block) @flexmock_proxy.mock.#{method_name}(*args, &block) end
1090
1138
  }
1091
1139
  end
1092
1140
 
@@ -1095,9 +1143,10 @@ class FlexMock
1095
1143
  def restore_original_definition(method_name)
1096
1144
  method_def = @method_definitions[method_name]
1097
1145
  if method_def
1098
- sclass.class_eval {
1099
- define_method(method_name, &method_def)
1100
- }
1146
+ the_alias = new_name(method_name)
1147
+ sclass.class_eval do
1148
+ alias_method(method_name, the_alias)
1149
+ end
1101
1150
  end
1102
1151
  end
1103
1152
 
@@ -1111,6 +1160,11 @@ class FlexMock
1111
1160
  def detached?
1112
1161
  @obj.nil?
1113
1162
  end
1114
-
1163
+
1164
+ # Generate a name to be used to alias the original behavior.
1165
+ def new_name(old_name)
1166
+ "flexmock_original_behavior_for_#{old_name}"
1167
+ end
1168
+
1115
1169
  end
1116
1170
  end
@@ -22,6 +22,9 @@ class TestStubbingOnNew < Test::Unit::TestCase
22
22
  def wag
23
23
  :tail
24
24
  end
25
+ def self.make
26
+ new
27
+ end
25
28
  end
26
29
 
27
30
  class Cat
@@ -43,25 +46,42 @@ class TestStubbingOnNew < Test::Unit::TestCase
43
46
  :unstubbed
44
47
  end
45
48
  end
49
+
50
+ def test_new_instances_requires_block
51
+ ex = assert_raise(ArgumentError) {
52
+ flexstub(Dog).new_instances
53
+ }
54
+ end
46
55
 
47
- def test_any_instance_allows_stubbing_of_existing_methods
48
- flexstub(Dog).any_instance do |obj|
56
+ def test_new_instances_allows_stubbing_of_existing_methods
57
+ flexstub(Dog).new_instances do |obj|
49
58
  obj.should_receive(:bark).and_return(:whimper)
50
59
  end
51
60
  m = Dog.new
52
61
  assert_equal :whimper, m.bark
53
62
  end
54
63
 
55
- def test_any_instance_stubs_still_have_existing_methods
56
- flexstub(Dog).any_instance do |obj|
64
+ def test_any_instance_still_works_for_backwards_compatibility
65
+ message = redirect_error {
66
+ flexstub(Dog).any_instance do |obj|
67
+ obj.should_receive(:bark).and_return(:whimper)
68
+ assert_match(/deprecated/, message)
69
+ end
70
+ }
71
+ m = Dog.new
72
+ assert_equal :whimper, m.bark
73
+ end
74
+
75
+ def test_new_instances_stubs_still_have_existing_methods
76
+ flexstub(Dog).new_instances do |obj|
57
77
  obj.should_receive(:bark).and_return(:whimper)
58
78
  end
59
79
  m = Dog.new
60
80
  assert_equal :tail, m.wag
61
81
  end
62
82
 
63
- def test_any_instance_will_pass_args_to_new
64
- flexstub(Cat).any_instance do |obj|
83
+ def test_new_instances_will_pass_args_to_new
84
+ flexstub(Cat).new_instances do |obj|
65
85
  obj.should_receive(:meow).and_return(:scratch)
66
86
  end
67
87
  x = :not_called
@@ -71,8 +91,23 @@ class TestStubbingOnNew < Test::Unit::TestCase
71
91
  assert_equal :called, x
72
92
  end
73
93
 
74
- def test_any_instance_stub_verification_happens_on_teardown
75
- flexstub(Dog).any_instance do |obj|
94
+ # Some versions of the software had problems invoking the block after a
95
+ # second stubbing.
96
+ def test_new_gets_block_after_restubbing
97
+ flexstub(Cat).new_instances { }
98
+ x = :not_called
99
+ m = Cat.new("Fido") { x = :called }
100
+ assert_equal :called, x
101
+ flexmock_teardown
102
+
103
+ flexstub(Cat).new_instances { }
104
+ x = :not_called
105
+ m = Cat.new("Fido") { x = :called }
106
+ assert_equal :called, x
107
+ end
108
+
109
+ def test_new_instances_stub_verification_happens_on_teardown
110
+ flexstub(Dog).new_instances do |obj|
76
111
  obj.should_receive(:bark).once.and_return(nil)
77
112
  end
78
113
 
@@ -81,14 +116,54 @@ class TestStubbingOnNew < Test::Unit::TestCase
81
116
  assert_match(/method 'bark\(.*\)' called incorrect number of times/, ex.message)
82
117
  end
83
118
 
84
- def test_any_instance_reports_error_on_non_classes
119
+ def test_new_instances_reports_error_on_non_classes
85
120
  ex = assert_raise(ArgumentError) {
86
- flexstub(Dog.new).any_instance do |obj|
121
+ flexstub(Dog.new).new_instances do |obj|
87
122
  obj.should_receive(:hi)
88
123
  end
89
124
  }
90
125
  assert_match(/Class/, ex.message)
91
- assert_match(/any_instance/, ex.message)
126
+ assert_match(/new_instances/, ex.message)
127
+ end
128
+
129
+ def test_can_stub_objects_created_with_allocate_instead_of_new
130
+ flexstub(Dog).new_instances do |obj|
131
+ obj.should_receive(:bark).and_return(:whimper)
132
+ end
133
+ m = Dog.allocate
134
+ assert_equal :whimper, m.bark
135
+ end
136
+
137
+ def test_can_stub_objects_created_with_arbitrary_class_methods
138
+ flexstub(Dog).new_instances(:make) do |obj|
139
+ obj.should_receive(:bark).and_return(:whimper)
140
+ end
141
+ assert_equal :whimper, Dog.make.bark
142
+ end
143
+
144
+ def test_stubbing_arbitrary_class_methods_leaves_new_alone
145
+ flexstub(Dog).new_instances(:make) do |obj|
146
+ obj.should_receive(:bark).and_return(:whimper)
147
+ end
148
+ assert_equal :woof, Dog.new.bark
149
+ end
150
+
151
+ def test_stubbing_new_and_allocate_doesnt_double_stub_objects_on_new
152
+ counter = 0
153
+ flexstub(Dog).new_instances do |obj|
154
+ counter += 1
155
+ end
156
+ Dog.new
157
+ assert_equal 1, counter
158
+ end
159
+
160
+ def test_stubbing_new_and_allocate_doesnt_double_stub_objects_on_allocate
161
+ counter = 0
162
+ flexstub(Dog).new_instances do |obj|
163
+ counter += 1
164
+ end
165
+ Dog.allocate
166
+ assert_equal 1, counter
92
167
  end
93
168
 
94
169
  # Current behavior does not install stubs into the block passed to new.
@@ -96,7 +171,7 @@ class TestStubbingOnNew < Test::Unit::TestCase
96
171
  # moment, we assure that they are not stubbed, but I am willing to change
97
172
  # this in the future.
98
173
  def test_blocks_on_new_do_not_have_stubs_installed
99
- flexstub(Connection).any_instance do |new_con|
174
+ flexstub(Connection).new_instances do |new_con|
100
175
  new_con.should_receive(:post).and_return {
101
176
  :stubbed
102
177
  }
@@ -108,4 +183,17 @@ class TestStubbingOnNew < Test::Unit::TestCase
108
183
  end
109
184
  assert block_run
110
185
  end
186
+
187
+ def redirect_error
188
+ require 'stringio'
189
+ old_err = $stderr
190
+ $stderr = StringIO.new
191
+ yield
192
+ $stderr.string
193
+ rescue
194
+ $stderr = old_err
195
+ end
196
+ private :redirect_error
111
197
  end
198
+
199
+
data/test/test_mock.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  #---
4
- # Copyright 2006 by Jim Weirich (jweirich@one.net).
4
+ # Copyright 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
5
5
  # All rights reserved.
6
6
 
7
7
  # Permission is granted for use, copying, modification, distribution,
@@ -25,6 +25,13 @@ end
25
25
 
26
26
  class TestFlexMockShoulds < Test::Unit::TestCase
27
27
 
28
+ # Expected error messages on failures
29
+ COUNT_ERROR_MESSAGE = /\bcalled\s+incorrect\s+number\s+of\s+times\b/
30
+ NO_MATCH_ERROR_MESSAGE = /\bno\s+matching\s+handler\b/
31
+ AT_LEAST_ERROR_MESSAGE = /\bshould\s+be\s+called\s+at\s+least\b/
32
+ AT_MOST_ERROR_MESSAGE = /\bshould\s+be\s+called\s+at\s+most\b/
33
+ OUT_OF_ORDER_ERROR_MESSAGE = /\bcalled\s+out\s+of\s+order\b/
34
+
28
35
  def test_defaults
29
36
  FlexMock.use do |m|
30
37
  m.should_receive(:hi)
@@ -87,10 +94,10 @@ class TestFlexMockShoulds < Test::Unit::TestCase
87
94
  end
88
95
 
89
96
  def test__with_no_args_but_with_args
90
- ex = assert_failure do
97
+ ex = assert_failure(NO_MATCH_ERROR_MESSAGE) do
91
98
  FlexMock.use do |m|
92
- m.should_receive(:hi).with_no_args
93
- m.hi(1)
99
+ m.should_receive(:hi).with_no_args
100
+ m.hi(1)
94
101
  end
95
102
  end
96
103
  end
@@ -187,8 +194,8 @@ class TestFlexMockShoulds < Test::Unit::TestCase
187
194
  def test_arg_matching_with_no_match
188
195
  FlexMock.use do |m|
189
196
  m.should_receive(:hi).with(1).returns(10)
190
- assert_failure {
191
- assert_equal 20, m.hi(2)
197
+ assert_failure(NO_MATCH_ERROR_MESSAGE) {
198
+ assert_equal 20, m.hi(2)
192
199
  }
193
200
  end
194
201
  end
@@ -196,8 +203,8 @@ class TestFlexMockShoulds < Test::Unit::TestCase
196
203
  def test_arg_matching_with_string_doesnt_over_match
197
204
  FlexMock.use do |m|
198
205
  m.should_receive(:hi).with(String).returns(20)
199
- assert_failure {
200
- m.hi(1.0)
206
+ assert_failure(NO_MATCH_ERROR_MESSAGE) {
207
+ m.hi(1.0)
201
208
  }
202
209
  end
203
210
  end
@@ -205,8 +212,8 @@ class TestFlexMockShoulds < Test::Unit::TestCase
205
212
  def test_block_arg_given_to_no_args
206
213
  FlexMock.use do |m|
207
214
  m.should_receive(:hi).with_no_args.returns(20)
208
- assert_failure {
209
- m.hi { 1 }
215
+ assert_failure(NO_MATCH_ERROR_MESSAGE) {
216
+ m.hi { 1 }
210
217
  }
211
218
  end
212
219
  end
@@ -245,10 +252,10 @@ class TestFlexMockShoulds < Test::Unit::TestCase
245
252
  end
246
253
 
247
254
  def test_never_and_called_once
248
- ex = assert_failure do
255
+ ex = assert_failure(COUNT_ERROR_MESSAGE) do
249
256
  FlexMock.use do |m|
250
- m.should_receive(:hi).with(1).never
251
- m.hi(1)
257
+ m.should_receive(:hi).with(1).never
258
+ m.hi(1)
252
259
  end
253
260
  end
254
261
  end
@@ -261,19 +268,19 @@ class TestFlexMockShoulds < Test::Unit::TestCase
261
268
  end
262
269
 
263
270
  def test_once_but_never_called
264
- ex = assert_failure do
271
+ ex = assert_failure(COUNT_ERROR_MESSAGE) do
265
272
  FlexMock.use do |m|
266
- m.should_receive(:hi).with(1).returns(10).once
273
+ m.should_receive(:hi).with(1).returns(10).once
267
274
  end
268
275
  end
269
276
  end
270
277
 
271
278
  def test_once_but_called_twice
272
- ex = assert_failure do
279
+ ex = assert_failure(COUNT_ERROR_MESSAGE) do
273
280
  FlexMock.use do |m|
274
- m.should_receive(:hi).with(1).returns(10).once
275
- m.hi(1)
276
- m.hi(1)
281
+ m.should_receive(:hi).with(1).returns(10).once
282
+ m.hi(1)
283
+ m.hi(1)
277
284
  end
278
285
  end
279
286
  end
@@ -321,9 +328,9 @@ class TestFlexMockShoulds < Test::Unit::TestCase
321
328
  end
322
329
 
323
330
  def test_at_least_but_never_called
324
- ex = assert_failure do
331
+ ex = assert_failure(AT_LEAST_ERROR_MESSAGE) do
325
332
  FlexMock.use do |m|
326
- m.should_receive(:hi).with(1).returns(10).at_least.once
333
+ m.should_receive(:hi).with(1).returns(10).at_least.once
327
334
  end
328
335
  end
329
336
  end
@@ -337,11 +344,11 @@ class TestFlexMockShoulds < Test::Unit::TestCase
337
344
  end
338
345
 
339
346
  def test_at_least_and_exact
340
- ex = assert_failure do
347
+ ex = assert_failure(COUNT_ERROR_MESSAGE) do
341
348
  FlexMock.use do |m|
342
- m.should_receive(:hi).with(1).returns(10).at_least.once.once
343
- m.hi(1)
344
- m.hi(1)
349
+ m.should_receive(:hi).with(1).returns(10).at_least.once.once
350
+ m.hi(1)
351
+ m.hi(1)
345
352
  end
346
353
  end
347
354
  end
@@ -360,19 +367,19 @@ class TestFlexMockShoulds < Test::Unit::TestCase
360
367
  end
361
368
 
362
369
  def test_at_most_called_twice
363
- ex = assert_failure do
370
+ ex = assert_failure(AT_MOST_ERROR_MESSAGE) do
364
371
  FlexMock.use do |m|
365
- m.should_receive(:hi).with(1).returns(10).at_most.once
366
- m.hi(1)
367
- m.hi(1)
372
+ m.should_receive(:hi).with(1).returns(10).at_most.once
373
+ m.hi(1)
374
+ m.hi(1)
368
375
  end
369
376
  end
370
377
  end
371
378
 
372
379
  def test_at_most_and_at_least_called_never
373
- ex = assert_failure do
380
+ ex = assert_failure(AT_LEAST_ERROR_MESSAGE) do
374
381
  FlexMock.use do |m|
375
- m.should_receive(:hi).with(1).returns(10).at_least.once.at_most.twice
382
+ m.should_receive(:hi).with(1).returns(10).at_least.once.at_most.twice
376
383
  end
377
384
  end
378
385
  end
@@ -393,12 +400,12 @@ class TestFlexMockShoulds < Test::Unit::TestCase
393
400
  end
394
401
 
395
402
  def test_at_most_and_at_least_called_three_times
396
- ex = assert_failure do
403
+ ex = assert_failure(AT_MOST_ERROR_MESSAGE) do
397
404
  FlexMock.use do |m|
398
- m.should_receive(:hi).with(1).returns(10).at_least.once.at_most.twice
399
- m.hi(1)
400
- m.hi(1)
401
- m.hi(1)
405
+ m.should_receive(:hi).with(1).returns(10).at_least.once.at_most.twice
406
+ m.hi(1)
407
+ m.hi(1)
408
+ m.hi(1)
402
409
  end
403
410
  end
404
411
  end
@@ -416,18 +423,19 @@ class TestFlexMockShoulds < Test::Unit::TestCase
416
423
  end
417
424
 
418
425
  def test_call_counts_only_apply_to_matching_args_with_mismatch
419
- ex = assert_failure do
426
+ ex = assert_failure(COUNT_ERROR_MESSAGE) do
420
427
  FlexMock.use do |m|
421
- m.should_receive(:hi).with(1).once
422
- m.should_receive(:hi).with(2).twice
423
- m.should_receive(:hi).with(3)
424
- m.should_receive(:lo)
425
- m.hi(1)
426
- m.hi(2)
427
- m.lo
428
- 20.times { m.hi(3) }
428
+ m.should_receive(:hi).with(1).once
429
+ m.should_receive(:hi).with(2).twice
430
+ m.should_receive(:hi).with(3)
431
+ m.should_receive(:lo)
432
+ m.hi(1)
433
+ m.hi(2)
434
+ m.lo
435
+ 20.times { m.hi(3) }
429
436
  end
430
437
  end
438
+ assert_match(/hi\(2\)/, ex.message)
431
439
  end
432
440
 
433
441
  def test_ordered_calls_in_order
@@ -441,13 +449,13 @@ class TestFlexMockShoulds < Test::Unit::TestCase
441
449
  end
442
450
 
443
451
  def test_ordered_calls_out_of_order
444
- ex = assert_failure do
452
+ ex = assert_failure(OUT_OF_ORDER_ERROR_MESSAGE) do
445
453
  FlexMock.use 'm' do |m|
446
- m.should_receive(:hi).ordered
447
- m.should_receive(:lo).ordered
448
-
449
- m.lo
450
- m.hi
454
+ m.should_receive(:hi).ordered
455
+ m.should_receive(:lo).ordered
456
+
457
+ m.lo
458
+ m.hi
451
459
  end
452
460
  end
453
461
  end
@@ -463,13 +471,13 @@ class TestFlexMockShoulds < Test::Unit::TestCase
463
471
  end
464
472
 
465
473
  def test_order_calls_with_different_arg_lists_and_out_of_order
466
- ex = assert_failure do
474
+ ex = assert_failure(OUT_OF_ORDER_ERROR_MESSAGE) do
467
475
  FlexMock.use 'm' do |m|
468
- m.should_receive(:hi).with("one").ordered
469
- m.should_receive(:hi).with("two").ordered
470
-
471
- m.hi("two")
472
- m.hi("one")
476
+ m.should_receive(:hi).with("one").ordered
477
+ m.should_receive(:hi).with("two").ordered
478
+
479
+ m.hi("two")
480
+ m.hi("one")
473
481
  end
474
482
  end
475
483
  end
@@ -500,11 +508,11 @@ class TestFlexMockShoulds < Test::Unit::TestCase
500
508
  end
501
509
  end
502
510
 
503
- def test_grouped_ordering
511
+ def test_grouped_ordering_with_numbers
504
512
  FlexMock.use 'm' do |m|
505
- m.should_receive(:start).ordered(:start_group)
506
- m.should_receive(:flip).ordered(:flip_flop_group)
507
- m.should_receive(:flop).ordered(:flip_flop_group)
513
+ m.should_receive(:start).ordered(1)
514
+ m.should_receive(:flip).ordered(2)
515
+ m.should_receive(:flop).ordered(2)
508
516
  m.should_receive(:final).ordered
509
517
 
510
518
  m.start
@@ -517,9 +525,9 @@ class TestFlexMockShoulds < Test::Unit::TestCase
517
525
 
518
526
  def test_grouped_ordering_with_symbols
519
527
  FlexMock.use 'm' do |m|
520
- m.should_receive(:start).ordered(:group_one)
521
- m.should_receive(:flip).ordered(:group_two)
522
- m.should_receive(:flop).ordered(:group_two)
528
+ m.should_receive(:start).ordered(:start_group)
529
+ m.should_receive(:flip).ordered(:flip_flop_group)
530
+ m.should_receive(:flop).ordered(:flip_flop_group)
523
531
  m.should_receive(:final).ordered
524
532
 
525
533
  m.start
@@ -541,17 +549,44 @@ class TestFlexMockShoulds < Test::Unit::TestCase
541
549
  end
542
550
 
543
551
  def test_explicit_ordering_with_explicit_misorders
544
- assert_failure do
552
+ ex = assert_failure(OUT_OF_ORDER_ERROR_MESSAGE) do
545
553
  FlexMock.use 'm' do |m|
546
- m.should_receive(:hi).ordered(:first_group)
547
- m.should_receive(:lo).ordered(:second_group)
548
-
549
- m.lo
550
- m.hi
554
+ m.should_receive(:hi).ordered(:first_group)
555
+ m.should_receive(:lo).ordered(:second_group)
556
+
557
+ m.lo
558
+ m.hi
551
559
  end
552
560
  end
561
+ # TODO: It would be nice to get the group names in the error message.
562
+ # assert_match /first_group/, ex.message
563
+ # assert_match /second_group/, ex.message
553
564
  end
554
-
565
+
566
+ # Test submitted by Mikael Pahmp to correct expectation matching.
567
+ def test_ordering_with_explicit_no_args_matches_correctly
568
+ FlexMock.use("m") do |m|
569
+ m.should_receive(:foo).with_no_args.once.ordered
570
+ m.should_receive(:bar).with_no_args.once.ordered
571
+ m.should_receive(:foo).with_no_args.once.ordered
572
+ m.foo
573
+ m.bar
574
+ m.foo
575
+ end
576
+ end
577
+
578
+ # Test submitted by Mikael Pahmp to correct expectation matching.
579
+ def test_ordering_with_any_arg_matching_correctly_matches
580
+ FlexMock.use("m") do |m|
581
+ m.should_receive(:foo).with_any_args.once.ordered
582
+ m.should_receive(:bar).with_any_args.once.ordered
583
+ m.should_receive(:foo).with_any_args.once.ordered
584
+ m.foo
585
+ m.bar
586
+ m.foo
587
+ end
588
+ end
589
+
555
590
  def test_expectation_formating
556
591
  m = FlexMock.new("m")
557
592
  exp = m.should_receive(:f).with(1,"two", /^3$/).and_return(0).at_least.once
@@ -597,18 +632,41 @@ class TestFlexMockShoulds < Test::Unit::TestCase
597
632
  assert_equal :mkf, m2.mock_kernel_function
598
633
  end
599
634
 
600
- def assert_failure
601
- assert_raises(Test::Unit::AssertionFailedError) do yield end
635
+ # Assertion helper used to assert validation failure. If a
636
+ # message is given, then the error message should match the
637
+ # expected error message.
638
+ def assert_failure(message=nil)
639
+ ex = assert_raises(Test::Unit::AssertionFailedError) { yield }
640
+ if message
641
+ case message
642
+ when Regexp
643
+ assert_match message, ex.message
644
+ when String
645
+ assert ex.message.index(message), "Error message '#{ex.message}' should contain '#{message}'"
646
+ end
647
+ end
648
+ ex
602
649
  end
603
-
604
650
  end
605
651
 
606
652
  class TestFlexMockShouldsWithInclude < Test::Unit::TestCase
607
653
  include FlexMock::ArgumentTypes
608
- def test_include
654
+ def test_include_enables_unqualified_arg_type_references
609
655
  FlexMock.use("x") do |m|
610
656
  m.should_receive(:hi).with(any).once
611
657
  m.hi(1)
612
658
  end
613
659
  end
614
660
  end
661
+
662
+ class TestFlexMockArgTypesDontLeak < Test::Unit::TestCase
663
+ def test_unqualified_arg_type_references_are_undefined_by_default
664
+ ex = assert_raise(NameError) do
665
+ FlexMock.use("x") do |m|
666
+ m.should_receive(:hi).with(any).once
667
+ m.hi(1)
668
+ end
669
+ end
670
+ assert_match(/\bany\b/, ex.message, "Error message should mention 'any'")
671
+ end
672
+ end
@@ -10,6 +10,7 @@
10
10
  #+++
11
11
 
12
12
  require 'test/unit'
13
+ require 'fileutils'
13
14
  require 'flexmock'
14
15
 
15
16
  class TestStubbing < Test::Unit::TestCase
@@ -127,11 +128,35 @@ class TestStubbing < Test::Unit::TestCase
127
128
  end
128
129
 
129
130
  def test_original_behavior_is_restored_on_nonsingleton_methods_with_multiple_stubs
130
- flexstub(File).should_receive(:open).with("foo").once.and_return(:ok)
131
- flexstub(File).should_receive(:open).with("bar").once.and_return(:ok)
131
+ flexstub(Dir).should_receive(:chdir).with("xx").once.and_return(:ok1)
132
+ flexstub(Dir).should_receive(:chdir).with("yy").once.and_return(:ok2)
133
+ assert_equal :ok1, Dir.chdir("xx")
134
+ assert_equal :ok2, Dir.chdir("yy")
135
+
136
+ flexstub(Dir).mock_teardown
137
+
138
+ x = :not_called
139
+ Dir.chdir("test") do
140
+ assert_match %r{/test$}, Dir.pwd
141
+ x = :called
142
+ end
143
+ assert_equal :called, x
144
+ end
132
145
 
146
+ def test_stubbing_file_shouldnt_break_writing
147
+ flexstub(File).should_receive(:open).with("foo").once.and_return(:ok)
133
148
  assert_equal :ok, File.open("foo")
134
- assert_equal :ok, File.open("bar")
149
+ flexstub(File).mock_teardown
150
+
151
+ File.open("dummy.txt", "w") do |out|
152
+ assert out.is_a?(IO)
153
+ out.puts "XYZ"
154
+ end
155
+ text = nil
156
+ File.open("dummy.txt") { |f| text = f.read }
157
+ assert_equal "XYZ\n", text
158
+ ensure
159
+ FileUtils.rm_f("dummy.txt")
135
160
  end
136
161
 
137
162
  def test_original_behavior_is_restored_even_when_errors
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: flexmock
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.5.0
7
- date: 2007-02-10 00:00:00 -05:00
6
+ version: 0.5.1
7
+ date: 2007-04-09 00:00:00 -04:00
8
8
  summary: Simple and Flexible Mock Objects for Testing
9
9
  require_paths:
10
10
  - lib
@@ -50,6 +50,7 @@ files:
50
50
  - doc/releases/flexmock-0.4.2.rdoc
51
51
  - doc/releases/flexmock-0.4.3.rdoc
52
52
  - doc/releases/flexmock-0.5.0.rdoc
53
+ - doc/releases/flexmock-0.5.1.rdoc
53
54
  test_files: []
54
55
 
55
56
  rdoc_options:
@@ -66,6 +67,7 @@ extra_rdoc_files:
66
67
  - doc/releases/flexmock-0.4.2.rdoc
67
68
  - doc/releases/flexmock-0.4.3.rdoc
68
69
  - doc/releases/flexmock-0.5.0.rdoc
70
+ - doc/releases/flexmock-0.5.1.rdoc
69
71
  executables: []
70
72
 
71
73
  extensions: []