Perl:mocking-d-f和friends。如何将它们放入CORE::GLOBAL

Perl:mocking-d-f和friends。如何将它们放入CORE::GLOBAL,perl,mocking,Perl,Mocking,核心文档向我展示了如何愉快地模拟各种构建的Perl函数。但是,我不确定如何替换'-d'和c'。用我的方法。所以这实际上只是一个关于如何在CORE::GLOBAL中用破折号替换函数的问题 手动参考会很好 package Testing::MockDir; use strict; use warnings; use Exporter(); use Symbol 'qualify_to_ref'; *import = \&Exporter::import; our @EXPORT_OK

核心文档向我展示了如何愉快地模拟各种构建的Perl函数。但是,我不确定如何替换'-d'和c'。用我的方法。所以这实际上只是一个关于如何在CORE::GLOBAL中用破折号替换函数的问题

手动参考会很好

package Testing::MockDir;

use strict;
use warnings;
use Exporter();
use Symbol 'qualify_to_ref';

*import = \&Exporter::import;

our @EXPORT_OK = qw(SetMockDir UnsetMockDir);

our %EXPORT_TAGS = (
    'all' => \@EXPORT_OK,
);

my %path2List = ();
my %handle2List = ();

BEGIN {
    *CORE::GLOBAL::opendir = \&Testing::MockDir::opendir;
    *CORE::GLOBAL::readdir = \&Testing::MockDir::readdir;
    *CORE::GLOBAL::closedir = \&Testing::MockDir::closedir;

    ######################### the "-" is really the problem here
    *CORE::GLOBAL::-d = \&Testing::MockDir::mock_d; # This does not work <<<<<
}

sub mock_d ($) {
    die 'It worked';
}

sub SetMockDir {
    my ($path, @files) = @_;
    $path2List{$path} = [@files];
}

sub UnsetMockDir {
    my ($path) = @_;
    delete $path2List{$path};
}

sub opendir (*$) {
    my $handle = qualify_to_ref(shift, caller);
    my ($path) = @_;
    return CORE::opendir($handle, $path) unless defined $path2List{$path};
    $handle2List{$handle} = $path2List{$path};
    return 1;
}

sub readdir (*) {
    my $handle = qualify_to_ref(shift, caller);
    return CORE::readdir($handle) unless defined $handle2List{$handle};
    return shift @{$handle2List{$handle}} unless wantarray;

    my @files = @{$handle2List{$handle}};
    $handle2List{$handle} = [];
    return @files;
}

sub closedir (*) {
    my $handle = qualify_to_ref(shift, caller);
    return CORE::closedir($handle) unless defined $handle2List{$handle};
    delete $handle2List{$handle};
    return 1;
}

1;
包测试::MockDir;
严格使用;
使用警告;
使用Exporter();
使用符号“限定到参考”;
*导入=\&导出器::导入;
我们的@EXPORT_OK=qw(SetMockDir-UnsetMockDir);
我们的%EXPORT\u标签=(
“全部”=>\@EXPORT\u正常,
);
我的%path2List=();
我的%handle2List=();
开始{
*CORE::GLOBAL::opendir=\&Testing::MockDir::opendir;
*核心::全局::readdir=\&测试::MockDir::readdir;
*CORE::GLOBAL::closedir=\&Testing::MockDir::closedir;
#########################这里真正的问题是“-”

*CORE::GLOBAL::-d=\&Testing::MockDir::mock#d;#这不起作用这可能是不可能的。关于哪些函数可以被重写的部分很模糊。“许多”可以,“一些”不能,但除了少数示例之外,没有确定的列表

通常,我会试试这个:

{
    no strict 'refs';
    *{'CORE::GLOBAL::-d'} = \&Testing::MockDir::mock_d;
}

这不是语法错误,但没有覆盖
-d

核心::GLOBAL的效果。如果没有原型,GLOBAL就无法工作。我唯一能想到的方法是重写操作码树…这不是为胆小的人准备的。你可以通过和和大量的实验来完成它


最简单的方法是根据您的喜好创建一个临时目录结构。

您可以选择源过滤器路径:

package Testing::MockDir;
use Filter::Simple;
FILTER {   s/\s+\-d (\S+)/ Testing::MockDir::filetest 'd',$1/g };
sub filetest {
  my ($test, $file) = @_;
  print "Mocking  -$test $file\n";
  return 1;
}

(此示例代码不是很健壮。例如,它不会翻译
-d$dir
-d“dirname with spaces”
,但您可以增强它,直到它满足目标代码的需要).

问题是你的应用程序依赖于硬编码的文件规范。你应该参数化文件规范;然后你就不必再模拟了,你可以使用Directory::Scratch或其他什么工具。

谢谢大家的回答

最后我做的是,在每个模块/测试目标的基础上,我将带有“-d”的代码分解到它自己的函数中

# Because I cannot mock -d directly
sub dirExists {
    return -d shift;
}
然后,我可以用类似的方法替换测试模块中的这个函数

my $doesDirExist = 1;
*MyModule::dirExists   = \&main::mock_dirExists;

sub mock_dirExists {
    return $doesDirExist;
}

这很难看,但我不想耽搁太久,而且出于我的目的,它工作得很好

如果是这样的话,那么我必须使目标代码更易于测试。Thanksoferriding CORE::GLOBAL必须在开始时进行,否则Perl将看不到它。这是一个性能问题。无论如何,CORE::GLOBAL只适用于原型s、 -d没有原型。这是一个有趣的想法…源代码转换…非常简洁谢谢!为什么
*import=\&Exporter::import;
而不是
使用Exporter'import';