How do I mock Perl's built-in backticks operator?
Asked Answered
D

2

12

I'd like to unit test a Perl program of mine that is using backticks. Is there a way to mock the backticks so that they would do something different from executing the external command?

Another question shows what I need, but in Ruby. Unfortunately, I cannot choose to use Ruby for this project, nor do I want to avoid the backticks.

Diluvial answered 9/9, 2010 at 16:44 Comment(8)
Can you clarify "I do not want to avoid the backticks"?Zuzana
Vaguely related to this - I often write a things using system, or backtics then realise I want to check what command I am puitting out. I have thought of crating a diagnostic version of system.Blest
@justintime: patching IPC::System::Simple to use a $DEBUG flag would be very welcome, I think.Zuzana
You say "Ha Ha Ha, you are a stupid built-in." It annoys it to no end.Jannelle
"nor do I want to avoid the backticks". Why do people care so much about the syntax they use? Why is it so important to use backticks over writing a couple more lines in a subroutine to do what you need, or even to use a module like Git::Wrapper?Anlage
@Ether, @brian d foy: I wrote this to clarify my requirements. The question would be rather easy to answer if "system" were used or some other method instead of backticks, because one can easily replace a built-in method (perldoc.perl.org/perlsub.html#Overriding-Built-in-Functions) Do I care much about the syntax? Not really... although programming is always a quest for the most beautiful solution.Diluvial
Why not just not use backticks? Or wrap backticks?Anlage
"Why not just not use backticks?"... what do you mean by that?Diluvial
C
19

You can* mock the built-in readpipe function. Perl will call your mock function when it encounters a backticks or qx expression.

BEGIN {
  *CORE::GLOBAL::readpipe = \&mock_readpipe
};

sub mock_readpipe {
  wantarray ? ("foo\n") : "foo\n";
}

print readpipe("ls -R");
print `ls -R`;
print qx(ls -R);


$ perl mock-readpipe.pl
foo
foo
foo

* - if you have perl version 5.8.9 or later.

Clarance answered 9/9, 2010 at 16:51 Comment(2)
This seems to only work right in later perls. 5.8.8 only prints foo for readpipe(...) and not backticks or qx. Works as shown in 5.10.1Fann
Good catch Eric. This was changed in 5.8.9: search.cpan.org/~jesse/perl-5.12.2/pod/…Clarance
Z
2

Instead of using backticks, you can use capture from IPC::System::Simple, and then write a mock version of capture() in your unit test.

# application
use IPC::System::Simple qw(capture);
my $stuff = capture("some command");

# test script
{
     package IPC::System::Simple;
     sub capture
     {
         # do something else; perhaps a call to ok()
     }
}

# ... rest of unit test here
Zuzana answered 9/9, 2010 at 16:47 Comment(1)
If you are going to call a subroutine, just write your own wrapper so you don't have to mock at all.Anlage

© 2022 - 2024 — McMap. All rights reserved.