Unit testing 如何在file.pl中模拟func而不是模块

Unit testing 如何在file.pl中模拟func而不是模块,unit-testing,perl,Unit Testing,Perl,在这样一个场景中,最好不要更改代码,而是添加测试 要测试的代码file.pl get_name{ return 'sth'; } 测试测试文件t use Test::More; use Test::MockModule; require thefile.pl my $module = Test::MockModule->new('thefile.pl') $module->mock(get_name => sub { return 'othername' }); my

在这样一个场景中,最好不要更改代码,而是添加测试

要测试的代码
file.pl

get_name{
    return 'sth';
}
测试
测试文件t

use Test::More;
use Test::MockModule;
require thefile.pl
my $module = Test::MockModule->new('thefile.pl')
$module->mock(get_name => sub { return 'othername' });
my $name = get_name();
ok($name eq 'othername');
我得到

Invalid package name thefile.pl

您的问题是您将文件名用作一个裸字,因此Perl将其解释为一个包名。由于
不是合法的标识符字符(可以在包名中使用的字符),因此会收到该警告

如果要使用文件名,请改用字符串:

require 'file.pl';
然后,在调用
Test::MockModule
时,它需要的是您在file.pl中定义的包的名称,而不是文件名

我不知道你在做什么,但当我想替换一个子例程定义时,我只是重写它。这是这个想法的核心,有很多方法可以暂时做到这一点。接口背后的代码,如
Test::MockModule
Hook::LexWrap
没有那么复杂:

BEGIN {
    require 'file.pl';

    package Some::Package;
    no warnings 'redefine';
    *get_name = sub { ... }
    }

glob(
*get_name
)有点棘手,但您的示例中已经显示了几乎所有其他内容。我在中展示了其中的一些技巧。在我的工作中,减少模块依赖项列表(尤其是在测试中)通常是值得的高级技巧。

替换子例程定义
,这正是我想要的,它可以工作,谢谢!