如何伪造输入到perl的钻石操作员?

bst*_*rre 13 io perl unit-testing diamond-operator

这个问题的答案描述了如何伪输入<STDIN>.我的目标与那个问题类似:我的单元测试需要假输入<>.

当我将相同的技术应用于假输入时<>,它不起作用.介绍级别的解释<>让我相信它是在命令行上没有给出文件时从STDIN读取的,但似乎并非如此.

我试图做的样本:

#!/usr/bin/perl -w

use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );

sub fake1 {
    my $fakeinput = "asdf\n";
    open my $stdin, '<', \$fakeinput
      or croak "Cannot open STDIN to read from string: $ERRNO";
    local *STDIN = $stdin;

    my $line = <>;
    print "fake1 line is $line\n";

    return 0;
}

sub fake2 {
    my $fakeinput = "asdf\n";
    open my $stdin, '<', \$fakeinput
      or croak "Cannot open STDIN to read from string: $ERRNO";
    local *STDIN = $stdin;

    my $line = <STDIN>;
    print "fake2 line is $line\n";

    return 0;
}

fake1();
fake2();
Run Code Online (Sandbox Code Playgroud)

fake2有效,fake1没有.一个示例会话("qwerty"是我打字):

$ perl /tmp/diamond.pl
qwerty
fake1 line is qwerty

fake2 line is asdf
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 我该如何伪造输入<>
  2. 在命令行上没有给出文件<>和之间的区别<STDIN>是什么?(即为什么链接问题中的技术适用于<STDIN>但不适用于<>?)

谢谢.

Mat*_*Mat 9

在第一次测试中试试这个:

open ARGV, '<', \$fakeinput
      or croak "Cannot open STDIN to read from string: $ERRNO";

my $line = <>;
print "fake1 line is $line\n";
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是不是"本地的" - 不知道你是否可以在本地制作.(你可以多次这样做,在每次测试前重置.)

  • 完善.事实上,我需要改变的是`local*ARGV = $ stdin;`.谢谢!手册中的关键似乎是"<>只是<ARGV>的同义词,这很神奇." ("魔法"部分让我感到有些害怕,但它似乎暂时起作用.) (2认同)
  • 实际上,`<>`是`readline(*ARGV);`的简写.有关详细信息,请参阅`perldoc -f readline`. (2认同)