This is a small example on how to mock a database using Test::MockDBI. It allows you to test your code without relying on an actual database, and gives you fine-grained control over returned values and possible situations. Also, the dbitest flag allows one to switch between the mocked and the real database connections easily.

Mark Leighton Fisher's (the module author) article An Introduction to Test::MockDBI is well-written overview and it is worth a read.

The t and t-src directories shipped with Test::MockDBI contains more examples on how to use the module.

db.pm - the module to test:
package db; # db.pm use strict; use warnings; use Data::Dumper; use DBI; our $dbh = undef; sub connect { # The arguments to DBI->connect are ignored by Test::MockDBI $dbh = DBI->connect('DBI:mysql:test', 'foo', 'bar'); } sub disconnect { $dbh->disconnect(); } sub select_i_from_t { my $sth = $dbh->prepare(q{select i from t}) or die "prepare failed"; $sth->execute() or die "execute failed"; my $arref = []; while (my $row = $sth->fetchrow_arrayref()) { push @$arref, $row->[0]; } return $arref; } 1; __END__
db.t - the test script for db.pm
# db.t use strict; use warnings; # Signal the we want to use Test::MockDBI BEGIN { push @ARGV, "--dbitest=42"; } use Test::More; use Test::MockDBI; BEGIN { plan tests => 3 } use_ok(q{db}); # Initialize fake database my $mock_dbi = Test::MockDBI::get_instance(); # Set return values for given query (when dbitest==42) my $vals = [ [123], [124], [125] ]; $mock_dbi->set_retval_scalar( 42, "select i from t", sub { shift @$vals } # take out an array ref element ); # Connect and run query ok(defined(db::connect()), q{Expect connect() to return true}); # Check returned array ref is_deeply( db::select_i_from_t(), [ 123, 124, 125 ], q{Expect select_i_from_t() to return arrayref [ 123, 124, 125 ]} ); __END__ =pod =head1 NAME db.t - Mock a database using Test::MockDBI =head1 SYNOPSIS prove db.t =head1 DESCRIPTION This is a small example on how to mock a database using L<Test::MockDBI>. It allows you to test your code I<without relying on an actual database>, and gives you fine-grained control over returned values and possible situations. Also, the C<--dbitest=\d+> flag allows one to switch between the mocked and the real database connections easily. The C<t> and C<t-src> directories shipped with L<Test::MockDBI> contains more examples on how to use the module. =head1 SEE ALSO An Introduction to Test::MockDBI - Article by Mark Leighton Fisher, July 21, 2005 http://www.perl.com/pub/a/2005/07/21/test_mockdbi.html Test::MockDBI Test::More =head1 AUTHOR andreas1234567 =cut
--
No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]

Replies are listed 'Best First'.
Re: Testing with Test::MockDBI
by CaMelRyder (Pilgrim) on May 07, 2010 at 20:12 UTC
    Does anybody know how make the data returned be sensitive to the actual querying parameters involved? Every example, I've seen has conveniently excluded mocking the results for a query with a where clause. The one example that I did find completely ignores the where clause. It seems to entail that the queries that our regexes are matching against are fully qualified SQL. In my experience, this is not the case. There are '?' placeholders for anything in the query that is literal. It seems to be completely oblivious to the fact that these parts of the query are bound when $sth->execute is called.

    Am I doing something wrong? It seems that this is a major oversight for the module if it doesn't have the ability to do query-sensitive results and would be appalled that anyone would say that the module allows you to have "fine-grained" control over the results.

    Can anyone illucidate the subject for me. Until, then I'm going to hold out, hoping that I'm completely wrong about the behavior of this module. I want to be wrong because I just blew a day getting our application at work to not crash when I use Test::MockDBI.

    ¥peace from CaMelRyder¥