Skip Menu |

This queue is for tickets about the Test-MockObject CPAN distribution.

Report information
The Basics
Id: 57702
Status: new
Priority: 0/
Queue: Test-MockObject

People
Owner: Nobody in particular
Requestors: mutant.nz [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: [Patch] unfake_module()
Attached is a patch for Test::MockObject - it adds a method unfake_module(), which undoes a fake_module(). I've found this necessary when running a bunch of tests under Test::Class::Load, as they're all run in the same process. If you fake something, but need the real version later, you have to manually do all the stuff unfake_module() does or you can get weird failures that don't happen when you run the test individually. I emailed this to you a while ago, but maybe this is a better channel?
Subject: tmo_patch.txt
diff -ruN Test-MockObject-1.09/lib/Test/MockObject.pm Test-MockObject-new/lib/Test/MockObject.pm --- Test-MockObject-1.09/lib/Test/MockObject.pm 2008-05-27 18:16:32.000000000 +1200 +++ Test-MockObject-new/lib/Test/MockObject.pm 2010-04-29 20:47:47.921409781 +1200 @@ -285,6 +285,11 @@ sub fake_module { my ($class, $modname, %subs) = @_; + + unless (ref $class) { + require Carp; + Carp::carp("fake_module() called as class method - calling of unfake_module() unsupported"); + } if ($class->check_class_loaded( $modname ) and ! keys %subs) { @@ -292,6 +297,8 @@ Carp::croak( "No mocked subs for loaded module '$modname'" ); } + $class->{_faked_module_name} = $modname if ref $class; + $modname =~ s!::!/!g; $INC{ $modname . '.pm' } = 1; @@ -306,15 +313,43 @@ my $type = reftype( $subs{ $sub } ) || ''; unless ( $type eq 'CODE' ) { - require Carp; - Carp::carp("'$sub' is not a code reference" ); + require Carp; + Carp::carp("'$sub' is not a code reference"); next; } no strict 'refs'; *{ $_[1] . '::' . $sub } = $subs{ $sub }; + push @{$class->{_faked_subs}}, $sub if ref $class; } } +sub unfake_module +{ + my ($class) = @_; + + require Carp; + Carp::croak("unfake_module() can't be called as a class method") unless ref $class; + + my $modname = $class->{_faked_module_name}; + + Carp::croak("Can't unfake module - don't know the module name. Did you call fake_module() as a class method?") unless $modname; + + $modname =~ s!::!/!g; + delete $INC{ $modname . '.pm' }; + + no warnings 'redefine'; + { + no strict 'refs'; + delete ${ $modname . '::' }{VERSION}; + } + + no strict 'refs'; + foreach my $sub (@{$class->{_faked_subs}}) { + undef *{ $class->{_faked_module_name} . '::' . $sub }; + } + +} + sub check_class_loaded { my ($self, $class, $load_flag) = @_; @@ -594,6 +629,20 @@ is( $s->{_cgi}, $mock, 'new() should create and store a new CGI object' ); +=item * C<unfake_module()> + +If you've called fake_module() (or fake_new()), you may need to 'unfake' it +later, so the real class can load. This is especially true if you have a whole +lot of tests running in one process (such as under Test::Class::Load). + +Note, that after calling unfake_module(), you'll need to load the real version +of the module in some way. If you're loading the modules you're testing with +use_ok(), you should be OK. + +Also note it's possible (but not recommended) to call fake_module() as a class +method. If you do this, unfake_module() will die if you call it, since it needs +to hold onto some state data in order to unfake the module. + =item * C<set_always(I<name>, I<value>)> Adds a method of the specified name that always returns the specified value. diff -ruN Test-MockObject-1.09/t/base.t Test-MockObject-new/t/base.t --- Test-MockObject-1.09/t/base.t 2008-05-27 18:16:32.000000000 +1200 +++ Test-MockObject-new/t/base.t 2010-04-29 20:43:16.828558283 +1200 @@ -3,8 +3,11 @@ use strict; use warnings; +use FindBin; +use lib "$FindBin::Bin/lib"; + my $package = 'Test::MockObject'; -use Test::More tests => 103; +use Test::More tests => 106; use_ok( $package ); # new() @@ -149,6 +152,13 @@ '... and should carp if it does not receive a function reference' ); } +$mock->fake_module( 'Dummy', foo => sub { 'fake dummy' } ); +is(Dummy::foo(), 'fake dummy', "Faked Dummy module"); +$mock->unfake_module(); + +use_ok('Dummy', "Loaded 'real' Dummy module"); +is(Dummy::foo(), 'bar', "Real Dummy method called"); + can_ok( $package, 'fake_new' ); $mock->fake_new( 'Some::Module' ); is( Some::Module->new(), $mock, diff -ruN Test-MockObject-1.09/t/lib/Dummy.pm Test-MockObject-new/t/lib/Dummy.pm --- Test-MockObject-1.09/t/lib/Dummy.pm 1970-01-01 12:00:00.000000000 +1200 +++ Test-MockObject-new/t/lib/Dummy.pm 2010-04-29 20:38:37.897117826 +1200 @@ -0,0 +1,11 @@ +# Dummy module for testing fake_module() / unfake_module() +package Dummy; + +use strict; +use warnings; + +sub foo { + return 'bar'; +} + +1; \ No newline at end of file
From: mutant.nz [...] gmail.com
Hi... just wondering if you'd had a chance to take a look at this? I know you're pretty busy with a lot of other stuff. If you don't have time for this module any more, I'd be more than happy to take it off your hands. I have a few ideas for things I'd like to add to it. Thanks.