The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Test::MockDBI - Mock DBI interface for testing

SYNOPSIS

  use Test::MockDBI;
     OR
  use Test::MockDBI qw( :all );

  Test::MockDBI::set_dbi_test_type(42);
  if (Test::MockDBI::get_dbi_test_type() == 42) {
    ...

  $mock_dbi = get_instance Test::MockDBI;

  $mock_dbi->bad_method(
   $method_name,
   $dbi_testing_type,
   $matching_sql);

  $mock_dbi->bad_param(
   $dbi_testing_type,
   $param_number,
   $param_value);

  $mock_dbi->set_retval_array(
   $dbi_testing_type,
   $matching_sql,
   @retval || CODEREF);
  $mock_dbi->set_retval_array(MOCKDBI_WILDCARD, ...

  $mock_dbi->set_retval_scalar(
   $dbi_testing_type,
   $matching_sql,
   $retval || CODEREF);
  $mock_dbi->set_retval_scalar(MOCKDBI_WILDCARD, ...

  $mock_dbi->set_rows(
   $dbi_testing_type,
   $matching_sql,
   $rows || CODEREF);
  $mock_dbi->set_rows(MOCKDBI_WILDCARD, ...

DESCRIPTION

Test::MockDBI provides a way to test DBI interfaces by creating rules for changing the DBI's behavior, then examining the standard output for matching patterns.

Testing using Test::MockDBI is enabled by setting the DBI testing type to a non-zero value. This can be done either by using a first program argument of "--dbitest[=TYPE]", or by using the class method Test::MockDBI::set_dbi_test_type(). (Supplying a first argument of "--dbitest[=TYPE]" often works well during testing.) TYPE is a simple integer (/^\d+$/). Supplying "--dbitest[=TYPE]" as a first argument works even if no other command-line processing is done, as Test::MockDBI does its own command-line processing to check for this first "--dbitest[=TYPE]" argument. You will want to add "--dbitest[=TYPE]" during a BEGIN block before the "use Test::MockDBI", so that the mock DBI is initialized as early as possible.

TYPE is optional, as a first argument of "--dbitest" will set the DBI testing type to 1 (one). DBI testing is also disabled by "--dbitest=0" (although this may not be generally useful). The class method Test::MockDBI::set_dbi_test_type() can also be used to set or change the DBI testing type.

When DBI testing is disabled, DBI is used as you would expect. This makes using Test::MockDBI transparent to your users.

The one exportable constant is:

MOCKDBI_WILDCARD

MOCKDBI_WILDCARD is the wildcard DBI testing type ("--dbitest=TYPE"), used when the fetch*() functions should always return the same value no matter what DBI testing type has been set.

External methods are:

get_dbi_test_type()

Returns the numeric DBI test type. The type is 0 when not testing the DBI interface.

set_dbi_test_type()

Sets the numeric DBI test type. The type is set to 0 if the argument cannot be interpreted as a simple integer digit string (/^\d+$/).

bad_method()

For the DBI method $method_name, when the DBI testing type is $dbi_testing_type and the current SQL matches the regex pattern in the string $matching_sql, make the function fail (usually by returning undef).

bad_param()

When the DBI testing type is $dbi_testing_type, make the fetch*() functions fail if one of their corresponding bind_param()s has parameter number $param_number with the value $param_value.

set_retval_array()

When the DBI testing type is $dbi_testing_type and the current SQL matches the pattern in the string $matching_sql, fetch() and fetchrow_array() return the contents of the array @retval. If retval is actually a CODEREF, the array returned from calling that subroutine will be returned instead.

set_retval_scalar()

When the DBI testing type is $dbi_testing_type and the current SQL matches the pattern in the string $matching_sql, fetchall_arrayref(), fetchrow_arrayref(), and fetchrow() return the scalar value $retval. If retval is actually a CODEREF, the scalar returned from calling that subroutine will be returned instead.

set_rows()

When the DBI testing type is $dbi_testing_type and the current SQL matches the pattern in the string $matching_sql, rows() returns the scalar value $rows. If retval is actually a CODEREF, the scalar returned from calling that subroutine will be returned instead.

NOTES

A good source of Test::MockDBI examples is how the t/*.t test programs examine the output (and modify the behavior) of the t/*.pl test programs.

bad_method() forces developers to use a different DBI testing type ("--dbitest=TYPE") for each different SQL pattern for a DBI method. This can be construed as a feature. (The workaround to this feature is to use MOCKDBI_WILDCARD.)

DBI fetch() and fetchrow_array() will return the undef value if the specified return value is a 1-element array with undef as the only element. I don't think this should prove a major obstacle in testing. It was coded this way due to how Perl currently handles a return value of undef when an array is expected, which is a one-element array with undef as the only element.

MOCKDBI_WILDCARD is only supported for the fetch*() return value setting methods, set_retval_scalar() and set_retval_array(). It probably does not make sense for the other external methods, as they are for creating DBI failures (and how often do you want your code to fail for all DBI testing types?)

If for some strange reason you should be installing Test::MockDBI into a system with DBI but without any DBD drivers (apart from DBD drivers bundled with DBI), you can use: perl samples/DBD-setup.pl cp samples/DBI.cfg . to create a sample DBM database (zipcodes.*) for testing Test::MockDBI (DBD::DBM ships with DBI).

DBI fetchrow() is supported, although it is so old it is no longer documented in the mainline DBI docs.

Test::MockDBI can be viewed as a "printf() and scratch head" helper for DBI applications.

SEE ALSO

DBI, Test::MockObject::Extends, Test::Simple, Test::More, perl(1)

DBD::Mock (another approach to testing DBI applications)

DBI trace() (still another approach to testing DBI applications)

IO::String (for capturing standard output)

AUTHOR

Mark Leighton Fisher, <mark-fisher@fisherscreek.com>

COPYRIGHT

Copyright 2004, Fisher's Creek Consulting, LLC. Copyright 2004, DeepData, Inc.

LICENSE

This code is released under the same licenses as Perl itself.