⬆️ ⬇️

Cheat Sheet on Perl Mock Objects

In rich Russian, unfortunately, there are not some words, so instead of starting the note with the words “Signing / Writing unit tests,” I have to lengthen the phrase.

In the process of writing unit tests, it is often necessary to look into old tests in order to quickly remember how to replace one or another object, so I decided that it was time to sketch a small cheat sheet, and maybe someone else would do it.

Immediately I ask you not to kick much, this is a cheat sheet, not a guide, so everything is very brief.



Substitution of random number generator





BEGIN { *CORE::GLOBAL::rand = sub {66}; } 




Time substitution



')

 use Test::MockTime qw( :all ); set_fixed_time( 1305636470 ); # do something restore_time(); 




CPAN: Test :: MockTime



Redis substitution





 use Test::Mock::Redis; my $redis = Test::Mock::Redis->new( server => 'whatever' ); 




CPAN: Test :: Mock :: Redis



Substitution DBMS





insert:

 use DBI; my $dbh = DBI->connect( 'dbi:Mock:', '', '' ); my $history = $dbh->{mock_all_history}; my $st = $history->[0]; # do that execute sql query # check is( $st->statement, $expected_sql, 'Query must be correct' ); is( $st->bound_params()->[0], 123456, 'Bound parameter must be correct' ); 


for select, you need to slip the fake results:

 $dbh->{mock_add_resultset} = { sql => 'SELECT emergency_dequeue_start()', results => [ [ 'emergency_dequeue_start' ], [ '11' ], ], }; 


Although only modules that work directly from the database need to be tested this way, in other cases it is better to replace the ORM modules or what replaces it because these tests are strongly tied to the module implementation, and it is better to bind only to the API.



CPAN: DBD :: Mock



HTTP script substitution (LWP :: UserAgent)





 use Test::Mock::LWP; $Mock_ua->mock( agent => sub {'My Agent 007'} ); $Mock_request->mock( content_type => sub {'application/x-www-form-urlencoded'} ); $Mock_response->mock( code => sub {200} ); $Mock_response->mock( content => sub {$response} ); $Mock_response->mock( is_error => sub {0} ); $Mock_response->mock( status_line => sub {'status line'} ); 


By setting the value of the $ response variable, we control the response of the “script”. If we use content () and want to check if the request was formed correctly, then we do this:

 $Mock_ua->mock( agent => sub { 'SMSOnline plc' } ); $Mock_request->mock( content_type => sub { 'application/x-www-form-urlencoded' } ); $Mock_request->mock( content => sub { ( my $self, $got_request ) = @_; $got_request; } ); $Mock_response->mock( code => sub { 200 } ); $Mock_response->mock( content => sub { $response } ); $Mock_response->mock( is_error => sub { 0 } ); $Mock_response->mock( status_line => sub { 'status line' } ); 


We can check that in $ got_request exactly what we wanted to send



CPAN: Test :: Mock :: LWP



Substitution of an arbitrary object





 my $mock = Test::MockObject->new(); Test::MockObject->fake_new( 'My::Module' ); my @txt_stat = (0, 0); $mock->mock( 'read_txt', sub { return @txt_stat; } ); $mock->mock( 'write_txt', sub { 1; } ); 


In @txt_stat we can change something for different tests.



CPAN: Test :: MockObject



Substitution Log4perl





Debug () method spoofing:

 my $logger = Test::MockObject->new(); Test::MockObject->fake_new( 'Log::Log4perl::init' ); $logger->mock( 'debug', sub { shift; diag shift; } ); 


If the tests pass normally, then diag shift; can be removed in order not to litter the output (it can be returned so it can be returned); similarly, other methods can also be pushed



Links



About Test :: MockObject

About DBD :: Mock

Links prompted by mrrico

Source: https://habr.com/ru/post/142667/



All Articles