DBD::Mock の execute() 時のエラーを偽装する
DBD::Mock は
$dbh->{mock_add_resultset} = { sql => 'BEGIN SOME_PROC(); END;', results => DBD::Mock->NULL_RESULTSET, failure => [ 12345, 'なんかエラー' ], };
こんな感じで、エラーコードを返すような仕込みができるらしいのだけど、RaiseError => 0 が指定されていると、期待通りにならない。*1execute() の戻り値を 0 にして、エラーコードを入れてほしいのだけど、例外を投げられてしまう。(RaiseError => 1 のときと同じ振る舞いをされてしまう)*2
しょうがないので、別の Mock を仕込んでエラーコードを入れるところとかを偽装する。なんかすげーバッドノウハウだな。。。
use Test::More; use DBI; use Test::Mock::Guard qw(mock_guard); use utf8; use strict; use warnnings; subtest 'other error', sub { my $error_code = '12345'; my $error_message = 'なんかエラー'; my $guard_dbh = mock_guard( 'DBI::db', +{ err => sub { $error_code }, errstr => sub { $error_message }, }); my $guard_sth = mock_guard( 'DBI::st', +{ execute => sub { 0 }, }); my $mock_dbh = DBI->connect('dbi:Mock:', '', '', +{ AutoCommit => 0, RaiseError => 0 }); $mock_dbh->{mock_add_resultset} = { # execute は偽装してるからこれはなくてもいい sql => 'BEGIN SOME_PROC(); END;', results => [], }; do_something_using_mock_dbh($mock_dbh); # ... }; # ...
こうなると、「DBD::Mock いらないじゃん」とも思うのだけど、他のテストでは Mock はさんでるのに、エラー返すときだけ普通の DBI (DBD::mysql)つかうのもそれはそれで気持ち悪いし。。。どうすればいいんですかね??