请帮我对该功能进行单元测试
func_for_test
。
我不明白如何模拟 get_dbh
函数(我使用 Test::Spec)。
ModuleForTests.pm
-----------------
use ModuleMysql;
my $dbh = get_dbh();
sub **func_for_test** {
my $sql = "DELETE ...";
$dbh->prepare($sql);
...
}
ModuleMysql.pm
-----------------
sub get_dbh {
state $dbh = DBI->connect ...
return $dbh;
}
我尝试了 DBD::Mock,但没有帮助。
$drh = DBI->install_driver( 'Mock' );
$drh->{mock_connect_fail} = 0;
$dbh = DBI->connect( 'DBI:Mock:', '', '' );
我也尝试过,但没有帮助 - 错误 Test::Spec;
my $dbh;
BEGIN {
$dbh = mock();
ModuleForTests->stubs(get_dbh => $dbh);
}
使用 Test::Spec 迫使您以不同的方式编写代码(许多人认为这是正确的方式)。
如果你想使用 Test::Spec,最好对你的类使用面向对象的设计。 ModuleForTest 中填充的 Lexical
$dbh
模拟起来很复杂,最好将数据库句柄存储在对象属性中。但它是 Perl,一切皆有可能。
#!/usr/bin/perl
use warnings;
use strict;
use Test::Spec;
use Sub::Override;
use DBI;
use ModuleMysql; # Needed here so we can override its get_dbh.
my $dbh;
BEGIN {
$dbh = 'DBI'->connect('DBI:Mock:', "", "") or die $DBI::errstr;
}
my $override;
BEGIN {
$override = 'Sub::Override'->new('ModuleMysql::get_dbh' => sub {
return $dbh
});
}
use ModuleForTest;
describe ModuleForTest => sub {
it 'prepares delete' => sub {
my $sth = ModuleForTest::func_for_test();
my $history = $dbh->{mock_all_history};
is($history->[0]->statement, 'DELETE ...');
};
};
runtests();
需要
BEGIN
块,因为我们需要在ModuleMysql加载之后、MoudleForTest调用它之前的精确时刻重新定义get_dbh。