所以我在设计中得到错误。子...重新定义。
假设我有一个子Get_Name_SSN ...进行数据库调用等。
我并不总是想在测试时调用db。
所以我创建了Testing.pm,它硬编码了一些在测试过程中使用的值。
我放use Testing;
现在我不需要调用db,如果我注释掉我自己的生产子程序。
我宁愿不通过我的代码评论出众多功能。我怀疑是否可能,但是我可以告诉perl使用导入的模块库中的函数而不是当前脚本中的函数吗?
MyScript.pl
use strict;
use warnings;
#only linux
#use diagnostics;
use TestModule;
sub get_name_ssn {
#call db
}
##################
package TestModule;
use Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(get_name_ssn ...
sub get_name_ssn {
#return key value pair
}
因此,当我想要制作时,注释掉使用TestModule。当我测试时,请离开TestModule。这不起作用,除非我也注释掉了本地子。
答案 0 :(得分:0)
将<{1}}行放在子例程定义之后。目前,use TestModule
中的子例程是最后定义的子例程,因此这是分配给名称MyScript.pl
的子例程。如果先放置子例程定义然后导入get_ssn_name
,则TestModule
中的子例程将是最后定义的子例程。
示例:
TestModule.pm
# TestModule.pm
sub main::foo { print "test function" };
1;
# script1.pl
use TestModule;
sub foo { print "real function" };
foo();
# script2.pl
sub foo { print "real function" };
use TestModule;
foo();
输出:
script1.pl
real function
输出:
script2.pl
答案 1 :(得分:0)
最后一个定义获胜,因此请确保您想要的那个定义最后显示。
您可以在运行时使用require
加载模块。到那时,即使require
行在词法上排在第一位,脚本中的那个也已定义。您可以将use
更改为:
require TestModule;
TestModule->import;
然而,这个问题有一个更好的解决方案。看起来您想要提供一个虚假的数据库例程进行测试。使用某种形式的依赖注入,而不是杂技,因此您可以自己提供数据库句柄。然后,您可以提供模拟数据库句柄进行测试。
答案 2 :(得分:0)
与brian_d_foy的建议一样,听起来你需要一个测试数据库。如果您有一个集中模块来保存数据库句柄,那么您将很容易触发整个代码库连接到该数据库而不是主数据库。然后你可以做任何正常的程序并测试你的真实代码。
以下是该类型数据库模块的示例。我已将其命名为MyProject::Database
。如果使用use MyProject::Database qw($dbh);
调用它将返回一个实时数据库句柄。但是,如果使用use MyProject::Database qw($dbh --testing);
进行调用,它将连接到测试数据库,而对此$dbh
的所有正常调用也必须使用测试数据库:
package MyProject::Database;
### This module is used to create and cache a Database Handle.
use base qw(Exporter);
our @EXPORT = qw($dbh);
our @EXPORT_OK = qw(getConnection)
;
use DBI;
our $DB_NAME = 'MyDB';
our $DB_USER = 'user';
our $DB_PASS = 'pass';
our $DB_HOST = 'localhost';
our $DB_TEST = 'MyTestingDB';
use strict;
use warnings;
# Global Database Handle
# One unique global database handle is sufficient for most environments.
# For that reason we provide this handle as a shared resource to all packges
# that use this module.
our $dbh;
# Initialize Database Handle
# This initializes the database handle when this module is used for the
# first time. For Apache, this should happen each time a child process is
# spawned.
sub import {
my $module = shift;
# Filter out options that cause alternative behavior
my %options;
@_ = map {/^-/ ? $options{$_}++ && () : $_} @_;
my $is_testing = delete $options{--testing};
die "Unknown options passed to " . __PACKAGE__ . ": " join(', ', keys %options)
if keys %options;
if ($is_testing) {
if ($dbh) {
warn "DBH already created in testing mode. Will be clobbered. Be sure to make call to for testing mode before all other use statements";
}
$dbh = getConnection($DB_TEST);
}
$dbh ||= getConnection();
MyProject::Database->export_to_level(1, $module, @_);
}
# Child Initialization Handler
# In some versions of apache/perl, the child initialization is not done
# properly, and the database handle is therefore no initialized. If this
# occurs, then a ChildInitHandler can be added pointing to here to ensure
# that a connect gets established.
sub handler {
$dbh = getConnection();
}
# Create a Database Handle
# This function creates a new Database Handle. It can be called with alternate
# connect parameters for testing environments etc.
sub getConnection {
my $name = shift // $DB_NAME;
my $user = shift // $DB_USER;
my $pass = shift // $DB_PASS;
my $host = shift // $DB_HOST;
# Database URL
my $url = "dbi:mysql:$name:$host";
my $handle = DBI->connect($url, $user, $pass) or die "DB connect failed: $DBI::errstr";
return $handle;
}
1;
__END__
然后将您的脚本编辑为以下内容:
#MyScript.pl
use strict;
use warnings;
use MyProject::Database qw($dbh --testing);
#...
my $database = $dbh->do(q{SELECT DATABASE()}) or die $dbh->errstr;
die "Not Testing DB" if $database ne 'MyTestingDB';
如果您还担心测试脚本编写者不记得指示测试模式,那么您可以强制所有测试脚本以.t
结尾。然后让MyProject::Database::import
验证$0
不会在.t
中结束,除非它在测试模式中被调用。