summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Cooper <scrapheap@heckrothindustries.co.uk>2019-12-22 20:07:57 +0000
committerJason Cooper <scrapheap@heckrothindustries.co.uk>2019-12-22 20:07:57 +0000
commit163f1b63f70c6c5831e15cb5485538d40ec33468 (patch)
treef41d7ac084ae407261b3769b3ed2278f1adf5a62
parent5fd586cb8a2591a142c4b38249589c338e97e25b (diff)
parent77da0c34a95ec1554db47a71edb17447de6eda86 (diff)
Merge branch 'feature/one-shot-failure' into 'master'
Feature: one shot failure Closes #2 See merge request scrapheap/DBD-Mock!19
-rw-r--r--lib/DBD/Mock.pm25
-rw-r--r--lib/DBD/Mock/db.pm56
-rw-r--r--t/023_statement_failure.t21
3 files changed, 70 insertions, 32 deletions
diff --git a/lib/DBD/Mock.pm b/lib/DBD/Mock.pm
index be239ac..3f81a68 100644
--- a/lib/DBD/Mock.pm
+++ b/lib/DBD/Mock.pm
@@ -447,7 +447,7 @@ according to the value of C<mock_can_connect>. So if C<mock_can_connect> were
to be set to C<0> (or off), then both C<Active> and C<ping> would return false
values (or C<0>).
-=item B<C<mock_add_resultset( \@resultset | \%sql_and_resultset )>>
+=item B<C<mock_add_resultset( \@resultset | \%resultset_and_options )>>
This stocks the database handle with a record set, allowing you to seed data
for your application to see if it works properly. Each recordset is a simple
@@ -498,7 +498,21 @@ Here is a sample usage, partially from the test suite:
# this will fetch rows from the second resultset...
my $row = $sth->fetchrow_arrayref;
-You can also associate a resultset with a particular SQL statement instead of
+It is possible to assign a hashref where the resultset must be given as
+value for the C<results> key:
+
+ $dbh->{mock_add_resultset} = {
+ results => [
+ [ 'foo', 'bar' ],
+ [ 'this_one', 'that_one' ],
+ [ 'this_two', 'that_two' ],
+ ],
+ };
+
+The reason for the hashref form is that you can add options as described
+in the following.
+
+You can associate a resultset with a particular SQL statement instead of
adding them in the order they will be fetched:
$dbh->{mock_add_resultset} = {
@@ -601,6 +615,13 @@ number and error string, in that order.
failure => [ 5, 'Ooops!' ],
};
+Without the C<sql> attribute the next statement will fail in any case:
+
+ $dbh->{mock_add_resultset} = {
+ results => DBD::Mock->NULL_RESULTSET,
+ failure => [ 5, 'Ooops!' ],
+ };
+
=item B<C<mock_get_info>>
This attribute can be used to set up values for C<get_info()>. It takes a
diff --git a/lib/DBD/Mock/db.pm b/lib/DBD/Mock/db.pm
index 5c65788..80ba29d 100644
--- a/lib/DBD/Mock/db.pm
+++ b/lib/DBD/Mock/db.pm
@@ -110,19 +110,22 @@ sub prepare {
else {
# If we have available resultsets seed the tracker with one
- my $rs;
- my $callback;
+ my ($rs, $callback, $failure);
+
if ( my $all_rs = $dbh->{mock_rs} ) {
if ( my $by_name = defined $all_rs->{named}{$statement} ? $all_rs->{named}{$statement} : first { $statement =~ m/$_->{regexp}/ } @{ $all_rs->{matching} } ) {
# We want to copy this, because it is meant to be reusable
$rs = [ @{ $by_name->{results} } ];
$callback = $by_name->{callback};
- if ( exists $by_name->{failure} ) {
- $track_params{failure} = [ @{ $by_name->{failure} } ];
- }
+ $failure = $by_name->{failure};
}
else {
$rs = shift @{ $all_rs->{ordered} };
+ if (ref($rs) eq 'HASH') {
+ $callback = $rs->{callback};
+ $failure = $rs->{failure};
+ $rs = [ @{ $rs->{results} } ];
+ }
}
}
@@ -131,6 +134,7 @@ sub prepare {
$track_params{return_data} = $rs;
$track_params{fields} = $fields;
$track_params{callback} = $callback;
+ $track_params{failure} = $failure;
if( $fields ) {
$sth->STORE( NAME => $fields );
@@ -344,51 +348,55 @@ sub STORE {
return $value;
}
elsif ( $attrib eq 'mock_add_resultset' ) {
+ my @copied_values;
+
$dbh->{mock_rs} ||= {
named => {},
ordered => [],
matching => [],
};
+
if ( ref $value eq 'ARRAY' ) {
- my @copied_values = @{$value};
+ @copied_values = @{$value};
push @{ $dbh->{mock_rs}{ordered} }, \@copied_values;
- return \@copied_values;
}
elsif ( ref $value eq 'HASH' ) {
my $name = $value->{sql};
- unless ($name) {
- die "Indexing resultset by name requires passing in 'sql' ",
- "as hashref key to 'mock_add_resultset'.\n";
- }
- my @copied_values = @{ $value->{results} ? $value->{results} : [] };
+ @copied_values = @{ $value->{results} ? $value->{results} : [] };
- if ( ref $name eq "Regexp" ) {
+ if (not defined $name) {
+ push @{ $dbh->{mock_rs}{ordered} }, {
+ results => \@copied_values,
+ callback => $value->{callback},
+ failure => ref($value->{failure}) ? [ @{ $value->{failure} } ] : undef,
+ };
+ }
+ elsif ( ref $name eq "Regexp" ) {
my $matching = {
regexp => $name,
results => \@copied_values,
callback => $value->{callback},
-
+ failure => ref($value->{failure}) ? [ @{ $value->{failure} } ] : undef,
};
- if ( exists $value->{failure} ) {
- $matching->{failure} = [ @{ $value->{failure} }, ];
- }
# either replace existing match or push
grep { $_->{regexp} eq $name && ($_ = $matching) } @{ $dbh->{mock_rs}{matching} }
or push @{ $dbh->{mock_rs}{matching} }, $matching;
- } else {
- $dbh->{mock_rs}{named}{$name} = { results => \@copied_values, callback => $value->{callback} };
- if ( exists $value->{failure} ) {
- $dbh->{mock_rs}{named}{$name}{failure} = [ @{ $value->{failure} }, ];
- }
}
-
- return \@copied_values;
+ else {
+ $dbh->{mock_rs}{named}{$name} = {
+ results => \@copied_values,
+ callback => $value->{callback},
+ failure => ref($value->{failure}) ? [ @{ $value->{failure} } ] : undef,
+ };
+ }
}
else {
die "Must provide an arrayref or hashref when adding ",
"resultset via 'mock_add_resultset'.\n";
}
+
+ return \@copied_values;
}
elsif ( $attrib eq 'mock_start_insert_id' ) {
if ( ref $value eq 'ARRAY' ) {
diff --git a/t/023_statement_failure.t b/t/023_statement_failure.t
index 7ae8df4..873565a 100644
--- a/t/023_statement_failure.t
+++ b/t/023_statement_failure.t
@@ -13,19 +13,28 @@ BEGIN {
# test misc. attributes
{
- my $dbh = DBI->connect('DBI:Mock:', 'user', 'pass');
+ my $dbh = DBI->connect('DBI:Mock:', '', '', {RaiseError => 1, PrintError => 0});
isa_ok($dbh, 'DBI::db');
-
+
+ $dbh->{mock_add_resultset} = {
+ results => DBD::Mock->NULL_RESULTSET,
+ failure => [ 3, 'Ohlala!' ],
+ };
+
+ my $sth = eval { $dbh->prepare('INSERT INTO bar (foo) VALUES (?)') };
+ ok(!$@, '$sth handle prepared correctly');
+ isa_ok($sth, 'DBI::st');
+
+ eval { $sth->execute('baz') };
+ ok( $@, '$sth handled executed and died' );
+
$dbh->{mock_add_resultset} = {
sql => qr/SELECT/,
results => DBD::Mock->NULL_RESULTSET,
failure => [ 5, 'Ooops!' ],
};
- $dbh->{PrintError} = 0;
- $dbh->{RaiseError} = 1;
-
- my $sth = eval { $dbh->prepare('SELECT foo FROM bar') };
+ $sth = eval { $dbh->prepare('SELECT foo FROM bar') };
ok(!$@, '$sth handle prepared correctly');
isa_ok($sth, 'DBI::st');