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