package tests::TestMockTest; use strict; use base qw/Lire::Test::TestCase/; use Lire::Test::Mock; sub new { return shift->SUPER::new( @_ ); } sub set_up { my $self = $_[0]; $self->SUPER::set_up(); $self->{'mock'} = new Lire::Test::Mock( 'FakePackage' ); return; } sub tear_down { my $self = $_[0]; $self->SUPER::tear_down(); return; } sub test_new { my $self = $_[0]; my $mock = new Lire::Test::Mock( 'FakePackage', 'method_1' => 1 ); $self->assert_isa( 'FakePackage', $mock ); $self->assert_deep_equals( bless( { '_base' => 'FakePackage', '_calls' => [], '_proxy' => 0, '_invocations' => { 'method_1' => [], 'method_2' => [], }, '_results' => { 'method_1' => 1 }, }, ref $self->{'mock'} ), $mock ); } sub test_new_proxy { my $self = $_[0]; my $mock = new_proxy Lire::Test::Mock( 'FakePackage', 1, 2, 3 ); $self->assert_isa( 'FakePackage', $mock ); $self->assert_deep_equals( bless( { 'args' => [ 1, 2, 3 ], '_base' => 'FakePackage', '_calls' => [], '_proxy' => 1, '_invocations' => { 'method_1' => [], 'method_2' => [], }, '_results' => {}, }, ref $self->{'mock'} ), $mock ); $self->assert_str_equals( 'method_1', $mock->method_1() ); $self->assert_str_equals( 'method_2', $mock->method_2() ); $mock->set_result( 'method_1', 'shadow' ); $self->assert_str_equals( 'shadow', $mock->method_1() ); $mock->set_result( 'method_1', undef ); $self->assert_str_equals( 'method_1', $mock->method_1() ); $self->assert_deep_equals( [ 'method_1', 'method_2', 'method_1', 'method_1' ], $mock->get_calls() ); } sub test_new_proxy_instance { my $self = $_[0]; my $fake = FakePackage->new( 1, 2, 3 ); my $mock = new_proxy Lire::Test::Mock( $fake ); $self->assert_isa( 'FakePackage', $mock ); $self->assert_deep_equals( bless( { 'args' => [ 1, 2, 3 ], '_base' => 'FakePackage', '_calls' => [], '_proxy' => 1, '_invocations' => { 'method_1' => [], 'method_2' => [], }, '_results' => {}, }, ref $self->{'mock'} ), $mock ); } sub test_set_mock_factory { my $self = $_[0]; $self->assert_dies( qr/no new\(\) method in class A_Package/, sub { Lire::Test::Mock->set_mock_factory( 'A_Package' ) } ); no strict 'refs'; my $or_factory = *{"BasePackage::new"}{'CODE'}; $self->assert_str_equals( $or_factory, FakePackage->can( 'new' ) ); $self->assert_deep_equals( {}, \%Lire::Test::Mock::FACTORIES ); Lire::Test::Mock->set_mock_factory( 'FakePackage', 'method_1' => 'test' ); $self->assert_deep_equals( { 'FakePackage' => undef }, \%Lire::Test::Mock::FACTORIES ); $self->assert_deep_equals( { 'FakePackage' => { 'method_1', 'test' } }, \%Lire::Test::Mock::FACTORY_RESULTS ); $self->assert_str_not_equals( $or_factory, FakePackage->can( 'new' ) ); Lire::Test::Mock->set_mock_factory( 'FakePackage' ); $self->assert_deep_equals( { 'FakePackage' => undef }, \%Lire::Test::Mock::FACTORIES ); my $mock = FakePackage->new(); $self->assert_isa( 'FakePackage', $mock ); $self->assert_num_equals( 1, $mock->{'_proxy'} ); $self->assert_num_equals( 1, $mock->invocation_count( 'new' ) ); $self->assert_deep_equals( [ 'FakePackage' ], $mock->get_invocation( 'new' ) ); $self->assert_str_equals( 'test', $mock->method_1() ); $self->assert_deep_equals( { 'FakePackage' => [ $mock ] }, \%Lire::Test::Mock::MOCK_INSTANCES ); $self->assert_deep_equals( [ $mock ], Lire::Test::Mock->mock_instances( 'FakePackage' ) ); $self->assert_dies( qr/no mock factory installed for class 'BasePackage'/, sub { Lire::Test::Mock->mock_instances( 'BasePackage' ) } ); Lire::Test::Mock->set_mock_factory( 'BasePackage' ); $self->assert_str_not_equals( $or_factory, BasePackage->can( 'new' ) ); $self->assert_deep_equals( {}, $Lire::Test::Mock::FACTORY_RESULTS{'BasePackage'} ); $self->assert_deep_equals( { 'BasePackage' => $or_factory, 'FakePackage' => undef, }, \%Lire::Test::Mock::FACTORIES ); $self->assert_str_equals( 'method_1', BasePackage->new()->method_1() ); Lire::Test::Mock->reset_factories(); $self->assert_deep_equals( {}, \%Lire::Test::Mock::FACTORIES ); $self->assert_deep_equals( {}, \%Lire::Test::Mock::FACTORY_RESULTS ); $self->assert_deep_equals( {}, \%Lire::Test::Mock::MOCK_INSTANCES ); $self->assert_str_equals( $or_factory, BasePackage->can( 'new' ) ); $self->assert_str_equals( $or_factory, FakePackage->can( 'new' ) ); } sub test_list_methods { my $self = $_[0]; my @methods = Lire::Test::Mock::list_methods( 'BasePackage' ); $self->assert_deep_equals( [ sort ( 'method_1', 'new' ) ], [ sort @methods ] ); @methods = Lire::Test::Mock::list_methods( 'FakePackage' ); $self->assert_deep_equals( [ sort ( 'method_1', 'method_2', 'new' ) ], [ sort @methods ] ); } sub test_get_calls { my $self = $_[0]; $self->{'mock'}->method_1(); $self->assert_deep_equals( [ 'method_1' ], $self->{'mock'}{'_calls'} ); $self->{'mock'}->method_2(); $self->assert_deep_equals( [ 'method_1', 'method_2' ], $self->{'mock'}{'_calls'} ); $self->{'mock'}->method_1(); $self->assert_deep_equals( [ 'method_1', 'method_2', 'method_1' ], $self->{'mock'}->get_calls() ); } sub test_set_result { my $self = $_[0]; $self->assert_dies( qr/no method 'method_3' defined in FakePackage/, sub { $self->{'mock'}->set_result( 'method_3' => undef ) } ); $self->{'mock'}->set_result( 'method_1' => 1 ); $self->assert_num_equals( 1, $self->{'mock'}{'_results'}{'method_1'} ); $self->assert_num_equals( 1, $self->{'mock'}->method_1() ); my $result = $self->{'mock'}->method_2(); $self->assert_null( $result, 'method_2() != undef'); my $sub = sub { return join ",", @_ }; $self->{'mock'}->set_result( 'method_1' => 3, 'method_2' => $sub ); $self->assert_num_equals( 3, $self->{'mock'}{'_results'}{'method_1'} ); $self->assert_str_equals( $sub, $self->{'mock'}{'_results'}{'method_2'} ); $self->assert_num_equals( 3, $self->{'mock'}->method_1() ); $self->assert_str_equals( join( ",", $self->{'mock'}, 3), $self->{'mock'}->method_2( 3 ) ); } sub test_invocation_count { my $self = $_[0]; $self->assert_dies( qr/no method 'method_3' defined in FakePackage/, sub { $self->{'mock'}->get_invocation( 'method_3' ) }); $self->assert_num_equals( 0, $self->{'mock'}->invocation_count( 'method_1' )); $self->{'mock'}->method_1(); $self->{'mock'}->method_1(); $self->assert_num_equals( 2, $self->{'mock'}->invocation_count( 'method_1' )); } sub test_get_invocation { my $self = $_[0]; $self->assert_dies( qr/no method 'method_3' defined in FakePackage/, sub { $self->{'mock'}->get_invocation( 'method_3' ) }); $self->assert_dies( qr/no invocation 0 for method 'method_1' /, sub { $self->{'mock'}->get_invocation( 'method_1' ) }); $self->{'mock'}->method_1(); $self->assert_deep_equals( [ [ $self->{'mock'} ] ], $self->{'mock'}{'_invocations'}{'method_1'} ); $self->{'mock'}->method_2( 3); $self->{'mock'}->method_2( 1, 2 ); $self->assert_deep_equals( [ [ $self->{'mock'}, 3 ], [ $self->{'mock'}, 1, 2 ], ], $self->{'mock'}{'_invocations'}{'method_2'} ); $self->assert_deep_equals( [ $self->{'mock'} ], $self->{'mock'}->get_invocation( 'method_1' ) ); $self->assert_deep_equals( [ $self->{'mock'}, 1, 2 ], $self->{'mock'}->get_invocation( 'method_2', 1) ); } package BasePackage; sub new { my $class = shift; return bless { 'args' => \@_ }, $class; } sub method_1 { 'method_1' } package FakePackage; use base qw/BasePackage/; sub method_2 { 'method_2' } 1;