Unit testing, without a database

Often we want to test some code that makes a whole lot of database calls, one way to do it is to set up a testing database and clean it up again when we are done. This works well, but is hard to do, and is hard to do as part of an install step when we may not even have a database server yet. What we have done in Koha is put these tests in a db_dependent directory, and the developers and Jenkins run them. But we can also do a lot of testing using things like Test::Mockmodule and DBD::Mock. Below is a snippet of code showing how we can use it for Koha.

use DBI;
use Test::More tests => 15;
use Test::MockModule;
BEGIN {
use_ok('C4::ItemType');
}
# Mock the call to create a database handler
my $module = new Test::MockModule('C4::Context');
$module->mock('_new_dbh', sub {
my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
|| die "Cannot create handle: $DBI::errstrn";
return $dbh });
# Mock data
my $itemtypes = [
['itemtype','description','rentalcharge','notforloan','imageurl','summary'],
['BK','Books',0,0,'',''],
['CD','CDRom',0,0,'','']
];
my $dbh = C4::Context->dbh(); # since we mocked _new_dbh we get a mock handle
my @itemtypes = C4::ItemType->all();
is(@itemtypes, 0, 'Testing all itemtypes is empty');
# This should run exactly one query so we can test
my $history = $dbh->{mock_all_history};
is(scalar(@{$history}), 1, 'Correct number of statements executed') ;
# Now lets add some mock data
$dbh->{mock_add_resultset} = $itemtypes;
@itemtypes = C4::ItemType->all();
is(@itemtypes, 2, 'ItemType->all should return an array with 2 elements');
is($itemtypes[0]->itemtype, 'BK', 'First itemtype is bk');
is($itemtypes[0]->fish,undef,'Calling a bad descriptor gives undef');

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s