1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 35;
use Test::Exception;
my $module = 'Test::MockObject::Extends';
use_ok( $module ) or exit;
# RT #17692 - cannot mock inline package without new()
{ package InlinePackageNoNew; sub foo; }
lives_ok { Test::MockObject::Extends->new( 'InlinePackageNoNew' ) }
'Mocking a package defined inline should not load anything';
# RT #15446 - isa() ignores type of blessed reference
# fake that Foo is loaded
$INC{'Foo.pm'} = './Foo.pm';
# create object
my $obj = bless {}, "Foo";
# test if the object is a reference to a hash
# silence warnings with UNIVERSAL::isa and Sub::Uplevel
no warnings 'uninitialized';
ok( $obj->isa( 'HASH' ), 'The object isa HASH' );
ok( UNIVERSAL::isa( $obj, 'HASH' ),
'...also if UNIVERSAL::isa() is called as a function' );
# wrap in mock object
Test::MockObject::Extends->new( $obj );
# test if the mock object is still a reference to a hash
ok( $obj->isa( 'HASH' ), 'The extended object isa HASH' );
ok( UNIVERSAL::isa( $obj, 'HASH' ),
"...also if UNIVERSAL::isa() is called as a function" );
# RT #14445 - inherited AUTOLOAD does not work correctly
CLASS:
{
package Foo;
use vars qw( $called_foo $called_autoload $method_name );
BEGIN
{
$called_foo = 0;
$called_autoload = 0;
$method_name = '';
}
sub new
{
bless {}, $_[0];
}
sub foo
{
$called_foo++;
return 'foo';
}
sub AUTOLOAD
{
$called_autoload++;
$method_name = $Foo::AUTOLOAD;
return 'autoload';
}
package Bar;
use vars qw( @ISA $called_this );
BEGIN
{
@ISA = 'Foo';
$called_this = 0;
}
sub this
{
$called_this++;
return 'this';
}
1;
}
my $object = Foo->new();
isa_ok( $object, 'Foo' );
# Create a trvial mocked autoloading object
my $mock = Test::MockObject::Extends->new($object);
isa_ok( $mock, 'Foo' );
# Call foo
is( $mock->foo(), 'foo', 'foo() returns as expected' );
is( $Foo::called_foo, 1, '$called_foo is incremented' );
is( $Foo::called_autoload, 0, '$called_autoload is unchanged' );
is( $Foo::method_name, '', '$method_name is unchanged' );
# Call an autoloaded method
is( $mock->bar(), 'autoload', 'bad() returns as expected' );
is( $Foo::called_autoload, 1, '$called_autoload is incremented' );
is( $Foo::method_name, 'Foo::bar', '$method_name is the correct value' );
$object = Bar->new();
isa_ok( $object, 'Foo' );
isa_ok( $object, 'Bar' );
# Create a non-trivial subclassed autoloading object
$mock = Test::MockObject::Extends->new( $object );
isa_ok( $mock, 'Foo' );
isa_ok( $mock, 'Bar' );
# Call foo
is( $mock->foo(), 'foo', 'foo() returns as expected' );
is( $Foo::called_foo, 2, '$called_foo is incremented' );
is( $Foo::called_autoload, 1, '$called_autoload is unchanged' );
is( $Bar::called_this, 0, '$called_this is unchanged' );
# Call this
is( $mock->this(), 'this', 'this() returns as expected' );
is( $Foo::called_foo, 2, '$called_foo is unchanged' );
is( $Foo::called_autoload, 1, '$called_autoload is unchanged' );
is( $Bar::called_this, 1, '$called_this is incremented' );
# Call an autoloaded method
is( $mock->that(), 'autoload', 'that() returns as expected' );
is( $Foo::called_autoload, 2, '$called_autoload is incremented' );
is( $Foo::method_name, 'Bar::that', '$method_name is set correctly' );
### This might demonstrate why the problem happened
is( $Bar::AUTOLOAD, undef,
"The \$AUTOLOAD for the object's actual class should be unset" );
is( $Foo::AUTOLOAD, 'Bar::that',
'The $AUTOLOAD that catches the call should contain the desired name'
);
# Get rid of a silly warning
$Bar::AUTOLOAD = $Bar::AUTOLOAD;
package Obj;
sub class_method { 'TRUE-CLASS-METHOD' }
package main;
my $o = Test::MockObject::Extends->new('Obj')->set_always(
-class_method => 'FAKED RESULT' );
is( $o->class_method, 'FAKED RESULT', 'class method mocked' );
# Don't reuse call info from destroyed object
sub extend
{
my $obj = bless {}, 'My';
$obj = Test::MockObject::Extends->new($obj);
ok ! $obj->call_pos(1), 'not called';
$obj->set_true('test');
$obj->test();
}
extend() for 1, 2;
|