我正在尝试修改我的测试,以便在完成时回滚任何数据库工作。但是,似乎我正在测试$ dbh-> commit的代码中的某个地方被明确调用。有没有办法覆盖DBI :: db对象的commit方法来完全转换提交?
我尝试过使用Test :: MockObject :: Extends,但这似乎削弱了$ dbh:
$dbh = ConnectToDB();
$dbh = Test::MockObject::Extends->new( $dbh );
$dbh->mock( 'commit', sub { warn("Caught you committing.") } );
稍后当我尝试使用$ dbh做一些工作时,我得到:
无法通过包“T :: MO :::: st”找到对象方法“fetchrow_array”
看起来我最终用模拟的$ dbh创建的$ sth没有正确设置。有没有人有一个很好的方法可以完全关闭特定$ dbh的提交?
我正在连接的数据库是Oracle,因为它的价值。
更新
事实证明,我们在一个非常类似于Axeman的答案的方法中覆盖了& DBI :: db :: commit,但实际上由于在存储过程中的一个存储过程中的恶意提交而发生了提交。我的考试。
答案 0 :(得分:2)
单元测试根本不应该真正与真实数据库交谈。一种常见的方法是使用DBD::Mock,DBD::CSV或SQLite将数据库驱动程序替换为虚假驱动程序,这样可以使用可以擦除的每个测试套件自定义的隔离测试数据每次运行后和/或保存以供分析。
答案 1 :(得分:2)
您可以使用the Callbacks attribute拦截并忽略commit()方法调用。
答案 2 :(得分:1)
你可以做这个Q& D想法:
{
my %old_commit;
sub toggle_commit {
my $dbh = shift;
my $class = blessed( $dbh );
if ( my $old_commit = $old_commit{ $class } ) {
my $symb
= do { no strict 'refs';
\*{ "$class\::commit" };
};
*$symb = undef;
unless ( $class->can( 'commit' )) {
*{ $symb } = $old_commit;
}
delete $old_commit{ $class };
}
else {
$old_commit{ $class } = $class->can( 'commit' );
{ no strict 'refs';
*{ "$class\::commit" } = sub { say "Committed!" };
}
}
}
}
是的,这是一个相当程度的Perl黑魔法。
你必须对其进行健全测试。由于这只应在测试时使用,因此您应该能够对代码进行分区,这样就不会在任何运行代码中乱码。
答案 3 :(得分:0)
我相信你想在连接时关闭AutoCommit。