1DBD::Mock(3)          User Contributed Perl Documentation         DBD::Mock(3)
2
3
4

NAME

6       DBD::Mock - Mock database driver for testing
7

SYNOPSIS

9        use DBI;
10
11        # connect to your as normal, using 'Mock' as your driver name
12        my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
13                      ⎪⎪ die "Cannot create handle: $DBI::errstr\n";
14
15        # create a statement handle as normal and execute with parameters
16        my $sth = $dbh->prepare( 'SELECT this, that FROM foo WHERE id = ?' );
17        $sth->execute( 15 );
18
19        # Now query the statement handle as to what has been done with it
20        my $mock_params = $sth->{mock_params};
21        print "Used statement: ", $sth->{mock_statement}, "\n",
22              "Bound parameters: ", join( ', ', @{ $params } ), "\n";
23

DESCRIPTION

25       Testing with databases can be tricky. If you are developing a system
26       married to a single database then you can make some assumptions about
27       your environment and ask the user to provide relevant connection infor‐
28       mation. But if you need to test a framework that uses DBI, particularly
29       a framework that uses different types of persistence schemes, then it
30       may be more useful to simply verify what the framework is trying to do
31       -- ensure the right SQL is generated and that the correct parameters
32       are bound. "DBD::Mock" makes it easy to just modify your configuration
33       (presumably held outside your code) and just use it instead of
34       "DBD::Foo" (like DBD::Pg or DBD::mysql) in your framework.
35
36       There is no distinct area where using this module makes sense. (Some
37       people may successfully argue that this is a solution looking for a
38       problem...) Indeed, if you can assume your users have something like
39       DBD::AnyData or DBD::SQLite or if you do not mind creating a dependency
40       on them then it makes far more sense to use these legitimate driver
41       implementations and test your application in the real world -- at least
42       as much of the real world as you can create in your tests...
43
44       And if your database handle exists as a package variable or something
45       else easily replaced at test-time then it may make more sense to use
46       Test::MockObject to create a fully dynamic handle. There is an excel‐
47       lent article by chromatic about using Test::MockObject in this and
48       other ways, strongly recommended. (See "SEE ALSO" for a link)
49
50       How does it work?
51
52       "DBD::Mock" comprises a set of classes used by DBI to implement a data‐
53       base driver. But instead of connecting to a datasource and manipulating
54       data found there it tracks all the calls made to the database handle
55       and any created statement handles. You can then inspect them to ensure
56       what you wanted to happen actually happened. For instance, say you have
57       a configuration file with your database connection information:
58
59         [DBI]
60         dsn      = DBI:Pg:dbname=myapp
61         user     = foo
62         password = bar
63
64       And this file is read in at process startup and the handle stored for
65       other procedures to use:
66
67         package ObjectDirectory;
68
69         my ( $DBH );
70
71         sub run_at_startup {
72            my ( $class, $config ) = @_;
73            $config ⎪⎪= read_configuration( ... );
74            my $dsn  = $config->{DBI}{dsn};
75            my $user = $config->{DBI}{user};
76            my $pass = $config->{DBI}{password};
77            $DBH = DBI->connect( $dsn, $user, $pass ) ⎪⎪ die ...;
78         }
79
80         sub get_database_handle {
81            return $DBH;
82         }
83
84       A procedure might use it like this (ignoring any error handling for the
85       moment):
86
87         package My::UserActions;
88
89         sub fetch_user {
90            my ( $class, $login ) = @_;
91            my $dbh = ObjectDirectory->get_database_handle;
92            my $sql = q{
93                SELECT login_name, first_name, last_name, creation_date, num_logins
94                  FROM users
95                 WHERE login_name = ?
96            };
97            my $sth = $dbh->prepare( $sql );
98            $sth->execute( $login );
99            my $row = $sth->fetchrow_arrayref;
100            return ( $row ) ? User->new( $row ) : undef;
101         }
102
103       So for the purposes of our tests we just want to ensure that:
104
105       1. The right SQL is being executed
106       2. The right parameters are bound
107
108       Assume whether the SQL actually works or not is irrelevant for this
109       test :-)
110
111       To do that our test might look like:
112
113         my $config = ObjectDirectory->read_configuration( ... );
114         $config->{DBI}{dsn} = 'DBI:Mock:';
115         ObjectDirectory->run_at_startup( $config );
116
117         my $login_name = 'foobar';
118         my $user = My::UserActions->fetch_user( $login_name );
119
120         # Get the handle from ObjectDirectory;
121         # this is the same handle used in the
122         # 'fetch_user()' procedure above
123         my $dbh = ObjectDirectory->get_database_handle();
124
125         # Ask the database handle for the history
126         # of all statements executed against it
127         my $history = $dbh->{mock_all_history};
128
129         # Now query that history record to
130         # see if our expectations match reality
131         cmp_ok(scalar(@{$history}), '==', 1, 'Correct number of statements executed' ;
132
133         my $login_st = $history->[0];
134         like($login_st->statement,
135             qr/SELECT login_name.*FROM users WHERE login_name = ?/sm,
136             'Correct statement generated' );
137
138         my $params = $login_st->bound_params;
139         cmp_ok(scalar(@{$params}), '==', 1, 'Correct number of parameters bound');
140         is($params->[0], $login_name, 'Correct value for parameter 1' );
141
142         # Reset the handle for future operations
143         $dbh->{mock_clear_history} = 1;
144
145       The list of properties and what they return is listed below. But in an
146       overall view:
147
148       ·   A database handle contains the history of all statements created
149           against it. Other properties set for the handle (e.g., 'PrintEr‐
150           ror', 'RaiseError') are left alone and can be queried as normal,
151           but they do not affect anything. (A future feature may track the
152           sequence/history of these assignments but if there is no demand it
153           probably will not get implemented.)
154
155       ·   A statement handle contains the statement it was prepared with plus
156           all bound parameters or parameters passed via "execute()". It can
157           also contain predefined results for the statement handle to
158           'fetch', track how many fetches were called and what its current
159           record is.
160
161       A Word of Warning
162
163       This may be an incredibly naive implementation of a DBD. But it works
164       for me ...
165

DBD::Mock

167       Since this is a normal DBI statement handle we need to expose our
168       tracking information as properties (accessed like a hash) rather than
169       methods.
170
171       Database Driver Properties
172
173       mock_connect_fail
174           This is a boolean property which when set to true (1) will not
175           allow DBI to connect. This can be used to simulate a DSN error or
176           authentication failure. This can then be set back to false (0) to
177           resume normal DBI operations. Here is an example of how this works:
178
179             # install the DBD::Mock driver
180             my $drh = DBI->install_driver('Mock');
181
182             $drh->{mock_connect_fail} = 1;
183
184             # this connection will fail
185             my $dbh = DBI->connect('dbi:Mock:', '', '') ⎪⎪ die "Cannot connect";
186
187             # this connection will throw an exception
188             my $dbh = DBI->connect('dbi:Mock:', '', '', { RaiseError => 1 });
189
190             $drh->{mock_connect_fail} = 0;
191
192             # this will work now ...
193             my $dbh = DBI->connect(...);
194
195           This feature is conceptually different from the 'mock_can_connect'
196           attribute of the $dbh in that it has a driver-wide scope, where
197           'mock_can_connect' is handle-wide scope. It also only prevents the
198           initial connection, any $dbh handles created prior to setting
199           'mock_connect_fail' to true (1) will still go on working just fine.
200
201       mock_data_sources
202           This is an ARRAY reference which holds fake data sources which are
203           returned by the Driver and Database Handle's "data_source()"
204           method.
205
206       mock_add_data_sources
207           This takes a string and adds it to the 'mock_data_sources'
208           attribute.
209
210       Database Handle Properties
211
212       mock_all_history
213           Returns an array reference with all history (a.k.a.
214           "DBD::Mock::StatementTrack") objects created against the database
215           handle in the order they were created. Each history object can then
216           report information about the SQL statement used to create it, the
217           bound parameters, etc..
218
219       mock_all_history_iterator
220           Returns a "DBD::Mock::StatementTrack::Iterator" object which will
221           iterate through the current set of "DBD::Mock::StatementTrack"
222           object in the  history. See the DBD::Mock::StatementTrack::Iterator
223           documentation below for more information.
224
225       mock_clear_history
226           If set to a true value all previous statement history operations
227           will be erased. This includes the history of currently open han‐
228           dles, so if you do something like:
229
230             my $dbh = get_handle( ... );
231             my $sth = $dbh->prepare( ... );
232             $dbh->{mock_clear_history} = 1;
233             $sth->execute( 'Foo' );
234
235           You will have no way to learn from the database handle that the
236           statement parameter 'Foo' was bound.
237
238           This is useful mainly to ensure you can isolate the statement his‐
239           tories from each other. A typical sequence will look like:
240
241               set handle to framework
242               perform operations
243               analyze mock database handle
244               reset mock database handle history
245               perform more operations
246               analyze mock database handle
247               reset mock database handle history
248               ...
249
250       mock_can_connect
251           This statement allows you to simulate a downed database connection.
252           This is useful in testing how your application/tests will perform
253           in the face of some kind of catastrophic event such as a network
254           outage or database server failure. It is a simple boolean value
255           which defaults to on, and can be set like this:
256
257             # turn the database off
258             $dbh->{mock_can_connect} = 0;
259
260             # turn it back on again
261             $dbh->{mock_can_connect} = 1;
262
263           The statement handle checks this value as well, so something like
264           this will fail in the expected way:
265
266             $dbh = DBI->connect( 'DBI:Mock:', '', '' );
267             $dbh->{mock_can_connect} = 0;
268
269             # blows up!
270             my $sth = eval { $dbh->prepare( 'SELECT foo FROM bar' ) });
271             if ( $@ ) {
272                # Here, $DBI::errstr = 'No connection present'
273             }
274
275           Turning off the database after a statement prepare will fail on the
276           statement "execute()", which is hopefully what you would expect:
277
278             $dbh = DBI->connect( 'DBI:Mock:', '', '' );
279
280             # ok!
281             my $sth = eval { $dbh->prepare( 'SELECT foo FROM bar' ) });
282             $dbh->{mock_can_connect} = 0;
283
284             # blows up!
285             $sth->execute;
286
287           Similarly:
288
289             $dbh = DBI->connect( 'DBI:Mock:', '', '' );
290
291             # ok!
292             my $sth = eval { $dbh->prepare( 'SELECT foo FROM bar' ) });
293
294             # ok!
295             $sth->execute;
296
297             $dbh->{mock_can_connect} = 0;
298
299             # blows up!
300             my $row = $sth->fetchrow_arrayref;
301
302           Note: The handle attribute "Active" and the handle method "ping"
303           will behave according to the value of "mock_can_connect". So if
304           "mock_can_connect" were to be set to 0 (or off), then both "Active"
305           and "ping" would return false values (or 0).
306
307       mock_add_resultset( \@resultset ⎪ \%sql_and_resultset )
308           This stocks the database handle with a record set, allowing you to
309           seed data for your application to see if it works properly.. Each
310           recordset is a simple arrayref of arrays with the first arrayref
311           being the fieldnames used. Every time a statement handle is created
312           it asks the database handle if it has any resultsets available and
313           if so uses it.
314
315           Here is a sample usage, partially from the test suite:
316
317             my @user_results = (
318               [ 'login', 'first_name', 'last_name' ],
319               [ 'cwinters', 'Chris', 'Winters' ],
320               [ 'bflay', 'Bobby', 'Flay' ],
321               [ 'alincoln', 'Abe', 'Lincoln' ],
322             );
323             my @generic_results = (
324               [ 'foo', 'bar' ],
325               [ 'this_one', 'that_one' ],
326               [ 'this_two', 'that_two' ],
327             );
328
329             my $dbh = DBI->connect( 'DBI:Mock:', '', '' );
330             $dbh->{mock_add_resultset} = \@user_results;    # add first resultset
331             $dbh->{mock_add_resultset} = \@generic_results; # add second resultset
332             my ( $sth );
333             eval {
334                $sth = $dbh->prepare( 'SELECT login, first_name, last_name FROM foo' );
335                $sth->execute();
336             };
337
338             # this will fetch rows from the first resultset...
339             my $row1 = $sth->fetchrow_arrayref;
340             my $user1 = User->new( login => $row->[0],
341                                   first => $row->[1],
342                                   last  => $row->[2] );
343             is( $user1->full_name, 'Chris Winters' );
344
345             my $row2 = $sth->fetchrow_arrayref;
346             my $user2 = User->new( login => $row->[0],
347                                   first => $row->[1],
348                                   last  => $row->[2] );
349             is( $user2->full_name, 'Bobby Flay' );
350             ...
351
352             my $sth_generic = $dbh->prepare( 'SELECT foo, bar FROM baz' );
353             $sth_generic->execute;
354
355             # this will fetch rows from the second resultset...
356             my $row = $sth->fetchrow_arrayref;
357
358           You can also associate a resultset with a particular SQL statement
359           instead of adding them in the order they will be fetched:
360
361             $dbh->{mock_add_resultset} = {
362                sql     => 'SELECT foo, bar FROM baz',
363                results => [
364                    [ 'foo', 'bar' ],
365                    [ 'this_one', 'that_one' ],
366                    [ 'this_two', 'that_two' ],
367                ],
368             };
369
370           This will return the given results when the statement 'SELECT foo,
371           bar FROM baz' is prepared. Note that they will be returned every
372           time the statement is prepared, not just the first. It should also
373           be noted that if you want, for some reason, to change the result
374           set bound to a particular SQL statement, all you need to do is add
375           the result set again with the same SQL statement and DBD::Mock will
376           overwrite it.
377
378           It should also be noted that the "rows" method will return the num‐
379           ber of records stocked in the result set. So if your code/applica‐
380           tion makes use of the "$sth->rows" method for things like UPDATE
381           and DELETE calls you should stock the result set like so:
382
383             $dbh->{mock_add_resultset} = {
384                sql     => 'UPDATE foo SET baz = 1, bar = 2',
385                # this will appear to have updated 3 rows
386                results => [[ 'rows' ], [], [], []],
387             };
388
389             # or ...
390
391             $dbh->{mock_add_resultset} = {
392                sql     => 'DELETE FROM foo WHERE bar = 2',
393                # this will appear to have deleted 1 row
394                results => [[ 'rows' ], []],
395             };
396
397           Now I admit this is not the most elegant way to go about this, but
398           it works for me for now, and until I can come up with a better
399           method, or someone sends me a patch ;) it will do for now.
400
401           If you want a given statement to fail, you will have to use the
402           hashref method and add a 'failure' key. That key can be handed an
403           arrayref with the error number and error string, in that order. It
404           can also be handed a hashref with two keys - errornum and
405           errorstring. If the 'failure' key has no useful value associated
406           with it, the errornum will be '1' and the errorstring will be
407           'Unknown error'.
408
409       mock_get_info
410           This attribute can be used to set up values for get_info(). It
411           takes a hashref of attribute_name/value pairs. See DBI for more
412           information on the information types and their meaning.
413
414       mock_session
415           This attribute can be used to set a current DBD::Mock::Session
416           object. For more information on this, see the DBD::Mock::Session
417           docs below. This attribute can also be used to remove the current
418           session from the $dbh simply by setting it to "undef".
419
420       mock_last_insert_id
421           This attribute is incremented each time an INSERT statement is
422           passed to "prepare" on a per-handle basis. It's starting value can
423           be set with  the 'mock_start_insert_id' attribute (see below).
424
425           This attribute also can be used with an ARRAY ref parameter, it's
426           behavior is slightly different in that instead of incrementing the
427           value for every "prepare" it will only increment for each "exe‐
428           cute". This allows it to be used over multiple "execute" calls in a
429           single $sth. It's usage looks like this:
430
431             $dbh->{mock_last_insert_id} = [ 'Foo', 10 ];
432
433             my $sth = $dbh->prepare('INSERT INTO Foo (foo, bar) VALUES(?, ?)');
434
435             $sth->execute(1, 2);
436             # $dbh->{mock_last_insert_id} == 10
437
438             $sth->execute(3, 4);
439             # $dbh->{mock_last_insert_id} == 11
440
441           For more examples, please refer to the test file
442           t/025_mock_last_insert_id.t.
443
444       mock_start_insert_id
445           This attribute can be used to set a start value for the
446           'mock_last_insert_id' attribute. It can also be used to effectively
447           reset the 'mock_last_insert_id' attribute as well.
448
449       mock_add_parser
450           DBI provides some simple parsing capabilities for 'SELECT' state‐
451           ments to ensure that placeholders are bound properly. And typically
452           you may simply want to check after the fact that a statement is
453           syntactically correct, or at least what you expect.
454
455           But other times you may want to parse the statement as it is pre‐
456           pared rather than after the fact. There is a hook in this mock
457           database driver for you to provide your own parsing routine or
458           object.
459
460           The syntax is simple:
461
462             $dbh->{mock_add_parser} = sub {
463                my ( $sql ) = @_;
464                unless ( $sql =~ /some regex/ ) {
465                    die "does not contain secret fieldname";
466                }
467             };
468
469           You can also add more than one for a handle. They will be called in
470           order, and the first one to fail will halt the parsing process:
471
472             $dbh->{mock_add_parser} = \&parse_update_sql;
473             $dbh->{mock_add-parser} = \&parse_insert_sql;
474
475           Depending on the 'PrintError' and 'RaiseError' settings in the
476           database handle any parsing errors encountered will issue a "warn"
477           or "die". No matter what the statement handle will be "undef".
478
479           Instead of providing a subroutine reference you can use an object.
480           The only requirement is that it implements the method "parse()" and
481           takes a SQL statement as the only argument. So you should be able
482           to do something like the following (untested):
483
484             my $parser = SQL::Parser->new( 'mysql', { RaiseError => 1 } );
485             $dbh->{mock_add_parser} = $parser;
486
487       mock_data_sources & mock_add_data_sources
488           These properties will dispatch to the Driver's properties of the
489           same name.
490
491       Database Driver Methods
492
493       last_insert_id
494           This returns the value of "mock_last_insert_id".
495
496       In order to capture begin_work(), commit(), and rollback(), DBD::Mock
497       will create statements for them, as if you had issued them in the
498       appropriate SQL command line program. They will go through the standard
499       prepare()-execute() cycle, meaning that any custom SQL parsers will be
500       triggered and DBD::Mock::Session will need to know about these state‐
501       ments.
502
503       begin_work
504           This will create a statement with SQL of "BEGIN WORK" and no param‐
505           eters.
506
507       commit
508           This will create a statement with SQL of "COMMIT" and no parame‐
509           ters.
510
511       rollback
512           This will create a statement with SQL of "ROLLBACK" and no parame‐
513           ters.
514
515       Statement Handle Properties
516
517       Active
518           Returns true if the handle is a 'SELECT' and has more records to
519           fetch, false otherwise. (From the DBI.)
520
521       mock_statement
522           The SQL statement this statement handle was "prepare"d with. So if
523           the handle were created with:
524
525             my $sth = $dbh->prepare( 'SELECT * FROM foo' );
526
527           This would return:
528
529             SELECT * FROM foo
530
531           The original statement is unmodified so if you are checking against
532           it in tests you may want to use a regex rather than a straight
533           equality check. (However if you use a phrasebook to store your SQL
534           externally you are a step ahead...)
535
536       mock_fields
537           Fields used by the statement. As said elsewhere we do no analysis
538           or parsing to find these, you need to define them beforehand. That
539           said, you do not actually need this very often.
540
541           Note that this returns the same thing as the normal statement prop‐
542           erty 'FIELD'.
543
544       mock_params
545           Returns an arrayref of parameters bound to this statement in the
546           order specified by the bind type. For instance, if you created and
547           stocked a handle with:
548
549             my $sth = $dbh->prepare( 'SELECT * FROM foo WHERE id = ? AND is_active = ?' );
550             $sth->bind_param( 2, 'yes' );
551             $sth->bind_param( 1, 7783 );
552
553           This would return:
554
555             [ 7738, 'yes' ]
556
557           The same result will occur if you pass the parameters via "exe‐
558           cute()" instead:
559
560             my $sth = $dbh->prepare( 'SELECT * FROM foo WHERE id = ? AND is_active = ?' );
561             $sth->execute( 7783, 'yes' );
562
563       mock_records
564           An arrayref of arrayrefs representing the records the mock state‐
565           ment was stocked with.
566
567       mock_num_records
568           Number of records the mock statement was stocked with; if never
569           stocked it is still 0. (Some weirdos might expect undef...)
570
571       mock_num_rows
572           This returns the same value as mock_num_records. And is what is
573           returned by the "rows" method of the statement handle.
574
575       mock_current_record_num
576           Current record the statement is on; returns 0 in the instances when
577           you have not yet called "execute()" and if you have not yet called
578           a "fetch" method after the execute.
579
580       mock_is_executed
581           Whether "execute()" has been called against the statement handle.
582           Returns 'yes' if so, 'no' if not.
583
584       mock_is_finished
585           Whether "finish()" has been called against the statement handle.
586           Returns 'yes' if so, 'no' if not.
587
588       mock_is_depleted
589           Returns 'yes' if all the records in the recordset have been
590           returned. If no "fetch()" was executed against the statement, or If
591           no return data was set this will return 'no'.
592
593       mock_my_history
594           Returns a "DBD::Mock::StatementTrack" object which tracks the
595           actions performed by this statement handle. Most of the actions are
596           separately available from the properties listed above, so you
597           should never need this.
598

DBD::Mock::Pool

600       This module can be used to emulate Apache::DBI style DBI connection
601       pooling. Just as with Apache::DBI, you must enable DBD::Mock::Pool
602       before loading DBI.
603
604         use DBD::Mock qw(Pool);
605         # followed by ...
606         use DBI;
607
608       While this may not seem to make a lot of sense in a single-process
609       testing scenario, it can be useful when testing code which assumes a
610       multi-process Apache::DBI pooled environment.
611

DBD::Mock::StatementTrack

613       Under the hood this module does most of the work with a
614       "DBD::Mock::StatementTrack" object. This is most useful when you are
615       reviewing multiple statements at a time, otherwise you might want to
616       use the "mock_*" statement handle attributes instead.
617
618       new( %params )
619           Takes the following parameters:
620
621           *   return_data: Arrayref of return data records
622
623           *   fields: Arrayref of field names
624
625           *   bound_params: Arrayref of bound parameters
626
627       statement (Statement attribute 'mock_statement')
628           Gets/sets the SQL statement used.
629
630       fields  (Statement attribute 'mock_fields')
631           Gets/sets the fields to use for this statement.
632
633       bound_params  (Statement attribute 'mock_params')
634           Gets/set the bound parameters to use for this statement.
635
636       return_data  (Statement attribute 'mock_records')
637           Gets/sets the data to return when asked (that is, when someone
638           calls 'fetch' on the statement handle).
639
640       current_record_num (Statement attribute 'mock_current_record_num')
641           Gets/sets the current record number.
642
643       is_active() (Statement attribute 'Active')
644           Returns true if the statement is a SELECT and has more records to
645           fetch, false otherwise. (This is from the DBI, see the 'Active'
646           docs under 'ATTRIBUTES COMMON TO ALL HANDLES'.)
647
648       is_executed( $yes_or_no ) (Statement attribute 'mock_is_executed')
649           Sets the state of the tracker 'executed' flag.
650
651       is_finished( $yes_or_no ) (Statement attribute 'mock_is_finished')
652           If set to 'yes' tells the tracker that the statement is finished.
653           This resets the current record number to '0' and clears out the
654           array ref of returned records.
655
656       is_depleted() (Statement attribute 'mock_is_depleted')
657           Returns true if the current record number is greater than the num‐
658           ber of records set to return.
659
660       num_fields
661           Returns the number of fields set in the 'fields' parameter.
662
663       num_rows
664           Returns the number of records in the current result set.
665
666       num_params
667           Returns the number of parameters set in the 'bound_params' parame‐
668           ter.
669
670       bound_param( $param_num, $value )
671           Sets bound parameter $param_num to $value. Returns the arrayref of
672           currently-set bound parameters. This corresponds to the
673           'bind_param' statement handle call.
674
675       bound_param_trailing( @params )
676           Pushes @params onto the list of already-set bound parameters.
677
678       mark_executed()
679           Tells the tracker that the statement has been executed and resets
680           the current record number to '0'.
681
682       next_record()
683           If the statement has been depleted (all records returned) returns
684           undef; otherwise it gets the current recordfor returning, incre‐
685           ments the current record number and returns the current record.
686
687       to_string()
688           Tries to give an decent depiction of the object state for use in
689           debugging.
690

DBD::Mock::StatementTrack::Iterator

692       This object can be used to iterate through the current set of
693       "DBD::Mock::StatementTrack" objects in the history by fetching the
694       'mock_all_history_iterator' attribute from a database handle. This
695       object is very simple and is meant to be a convience to make writing
696       long test script easier. Aside from the constructor ("new") this object
697       has only one method.
698
699           next
700
701           Calling "next" will return the next "DBD::Mock::StatementTrack"
702           object in the history. If there are no more "DBD::Mock::Statement‐
703           Track" objects available, then this method will return false.
704
705           reset
706
707           This will reset the internal pointer to the begining of the state‐
708           ment history.
709

DBD::Mock::Session

711       The DBD::Mock::Session object is an alternate means of specifying the
712       SQL statements and result sets for DBD::Mock. The idea is that you can
713       specify a complete 'session' of usage, which will be verified through
714       DBD::Mock. Here is an example:
715
716         my $session = DBD::Mock::Session->new('my_session' => (
717               {
718                   statement => "SELECT foo FROM bar", # as a string
719                   results   => [[ 'foo' ], [ 'baz' ]]
720               },
721               {
722                   statement => qr/UPDATE bar SET foo \= \'bar\'/, # as a reg-exp
723                   results   => [[]]
724               },
725               {
726                   statement => sub {  # as a CODE ref
727                           my ($SQL, $state) = @_;
728                           return $SQL eq "SELECT foo FROM bar";
729                           },
730                   results   => [[ 'foo' ], [ 'bar' ]]
731               },
732               {
733                   # with bound parameters
734                   statement    => "SELECT foo FROM bar WHERE baz = ? AND borg = ?",
735                   # check exact bound param value,
736                   # then check it against regexp
737                   bound_params => [ 10, qr/\d+/ ],
738                   results      => [[ 'foo' ], [ 'baz' ]]
739               }
740         ));
741
742       As you can see, a session is essentially made up a list of HASH refer‐
743       ences we call 'states'. Each state has a 'statement' and a set of
744       'results'. If DBD::Mock finds a session in the 'mock_session'
745       attribute, then it will pass the current $dbh and SQL statement to that
746       DBD::Mock::Session. The SQL statement will be checked against the
747       'statement'  field in the current state. If it passes, then the
748       'results' of the current state will get feed to DBD::Mock through the
749       'mock_add_resultset' attribute. We then advance to the next state in
750       the session, and wait for the next call through DBD::Mock. If at any
751       time the SQL statement does not match the current state's 'statement',
752       or the session runs out of available states, an error will be raised
753       (and propagated through the normal DBI error handling based on your
754       values for RaiseError and PrintError).
755
756       Also, as can be seen in the the session element, bound parameters can
757       also be supplied and tested. In this statement, the SQL is compared,
758       then when the statement is executed, the bound parameters are also
759       checked. The bound parameters much match in both number of parameters
760       and the parameters themselves, or an error will be raised.
761
762       As can also be seen in the example above, 'statement' fields can come
763       in many forms. The simplest is a string, which will be compared using
764       "eq" against the currently running statement. The next is a reg-exp
765       reference, this too will get compared against the currently running
766       statement. The last option is a CODE ref, this is sort of a catch-all
767       to allow for a wide range of SQL comparison approaches (including using
768       modules like SQL::Statement or SQL::Parser for detailed functional com‐
769       parisons). The first argument to the CODE ref will be the currently
770       active SQL statement to compare against, the second argument is a ref‐
771       erence to the current state HASH (in case you need to alter the
772       results, or store extra information). The CODE is evaluated in boolean
773       context and throws and exception if it is false.
774
775           new ($session_name, @session_states)
776
777           A $session_name can be optionally be specified, along with at least
778           one @session_states. If you don't specify a $session_name, then a
779           default one will be created for you. The @session_states must all
780           be HASH references as well, if this conditions fail, an exception
781           will be thrown.
782
783           verify_statement ($dbh, $SQL)
784
785           This will check the $SQL against the current state's 'statement'
786           value, and if it passes will add the current state's 'results' to
787           the $dbh. If for some reason the 'statement' value is bad, not of
788           the prescribed type, an exception is thrown. See above for more
789           details.
790
791           verify_bound_params ($dbh, $params)
792
793           If the 'bound_params' slot is available in the current state, this
794           will check the $params against the current state's 'bound_params'
795           value. Both number of parameters and the parameters themselves must
796           match, or an error will be raised.
797
798           reset
799
800           Calling this method will reset the state of the session object so
801           that it can be reused.
802

EXPERIMENTAL FUNCTIONALITY

804       All functionality listed here is highly experimental and should be used
805       with great caution (if at all).
806
807       Error handling in mock_add_resultset
808           We have added experimental erro handling in mock_add_resultset the
809           best example is the test file t/023_statement_failure.t, but it
810           looks something like this:
811
812             $dbh->{mock_add_resultset} = {
813                 sql => 'SELECT foo FROM bar',
814                 results => DBD::Mock->NULL_RESULTSET,
815                 failure => [ 5, 'Ooops!' ],
816             };
817
818           The 5 is the DBI error number, and 'Ooops!' is the error string
819           passed to DBI. This basically allows you to force an error condi‐
820           tion to occur when a given SQL statement is execute. We are cur‐
821           rently working on allowing more control on the 'when' and 'where'
822           the error happens, look for it in future releases.
823
824       Attribute Aliasing
825           Basically this feature allows you to alias attributes to other
826           attributes. So for instance, you can alias a commonly expected
827           attribute like 'mysql_insertid' to something DBD::Mock already has
828           like 'mock_last_insert_id'. While you can also just set
829           'mysql_insertid' yourself, this functionality allows it to take
830           advantage of things like the autoincrementing of the
831           'mock_last_insert_id' attribute.
832
833           Right now this feature is highly experimental, and has been added
834           as a first attempt to automatically handle some of the DBD specific
835           attributes which are commonly used/accessed in DBI programming. The
836           functionality is off by default so as to not cause any issues with
837           backwards compatability, but can easily be turned on and off like
838           this:
839
840             # turn it on
841             $DBD::Mock::AttributeAliasing++;
842
843             # turn it off
844             $DBD::Mock::AttributeAliasing = 0;
845
846           Once this is turned on, you will need to choose a database specific
847           attribute aliasing table like so:
848
849             DBI->connect('dbi:Mock:MySQL', '', '');
850
851           The 'MySQL' in the DSN will be picked up and the MySQL specific
852           attribute aliasing will be used.
853
854           Right now only MySQL is supported by this feature, and even that
855           support is very minimal. Currently the MySQL $dbh and $sth
856           attributes 'mysql_insertid' are aliased to the $dbh attribute
857           'mock_last_insert_id'. It is possible to add more aliases though,
858           using the "DBD::Mock:_set_mock_attribute_aliases" function (see the
859           source code for details).
860

BUGS

862       Odd $dbh attribute behavior
863           When writing the test suite I encountered some odd behavior with
864           some $dbh attributes. I still need to get deeper into how DBD's
865           work to understand what it is that is actually doing wrong.
866

TO DO

868       Make DBD specific handlers
869           Each DBD has its own quirks and issues, it would be nice to be able
870           to handle those issues with DBD::Mock in some way. I have an number
871           of ideas already, but little time to sit down and really flesh them
872           out. If you have any suggestions or thoughts, feel free to email me
873           with them.
874
875       Enhance the DBD::Mock::StatementTrack object
876           I would like to have the DBD::Mock::StatementTrack object handle
877           more of the mock_* attributes. This would encapsulate much of the
878           mock_* behavior in one place, which would be a good thing.
879
880           I would also like to add the ability to bind a subroutine (or pos‐
881           sibly an object) to the result set, so that the results can be
882           somewhat more dynamic and allow for a more realistic interaction.
883

CODE COVERAGE

885       We use Devel::Cover to test the code coverage of my tests, below is the
886       Devel::Cover report on this module test suite.
887
888         ---------------------------- ------ ------ ------ ------ ------ ------ ------
889         File                           stmt   bran   cond    sub    pod   time  total
890         ---------------------------- ------ ------ ------ ------ ------ ------ ------
891         blib/lib/DBD/Mock.pm           92.0   86.6   77.9   95.3    0.0  100.0   89.5
892         Total                          92.0   86.6   77.9   95.3    0.0  100.0   89.5
893         ---------------------------- ------ ------ ------ ------ ------ ------ ------
894

SEE ALSO

896       DBI
897
898       DBD::NullP, which provided a good starting point
899
900       Test::MockObject, which provided the approach
901
902       Test::MockObject article -
903       <http://www.perl.com/pub/a/2002/07/10/tmo.html>
904
905       Perl Code Kata: Testing Databases -
906       <http://www.perl.com/pub/a/2005/02/10/database_kata.html>
907

DISCUSSION GROUP

909       We have created a DBD::Mock google group for discussion/questions about
910       this module.
911
912       <http://groups-beta.google.com/group/DBDMock>
913

ACKNOWLEDGEMENTS

915       Thanks to Ryan Gerry for his patch in RT #26604
916       Thanks to Marc Beyer for his patch in RT #16951
917       Thanks to Justin DeVuyst for the mock_connect_fail idea
918       Thanks to Thilo Planz for the code for "bind_param_inout"
919       Thanks to Shlomi Fish for help tracking down RT Bug #11515
920       Thanks to Collin Winter for the patch to fix the "begin_work()", "com‐
921       mit()" and "rollback()" methods.
922       Thanks to Andrew McHarg <amcharg@acm.org> for "fetchall_hashref()",
923       "fetchrow_hashref()" and "selectcol_arrayref()" methods and tests.
924       Thanks to Andrew W. Gibbs for the "mock_last_insert_ids" patch and test
925       Thanks to Chas Owens for patch and test for the "mock_can_prepare",
926       "mock_can_execute", and "mock_can_fetch" features.
927
929       Copyright (C) 2004 Chris Winters <chris@cwinters.com>
930
931       Copyright (C) 2004-2007 Stevan Little <stevan@iinteractive.com>
932
933       Copyright (C) 2007 Rob Kinyon <rob.kinyon@gmail.com>
934
935       This library is free software; you can redistribute it and/or modify it
936       under the same terms as Perl itself.
937

AUTHORS

939       Chris Winters <chris@cwinters.com>
940
941       Stevan Little <stevan@iinteractive.com>
942
943       Rob Kinyon <rob.kinyon@gmail.com>
944
945
946
947perl v5.8.8                       2007-10-24                      DBD::Mock(3)
Impressum