Reputation: 1281
I have a function which looks like the one written below. I need to write a unit test for the below function. I am not able to mock few values.
use File::Basename;
use File::Copy;
use File::Temp qw(tempdir);
our $CONFIG="/home/chetanv/svf.xml";
copyConfigFiles();
sub copyConfigFiles {
my $temp_dir = File::Temp->newdir();
my $targetpath = dirname("$CONFIG");
`sudo touch $tempdir/myfile`;
make_path($targetpath) if ( ! -d $targetpath );
File::Copy::copy("$temp_dir/myfile", $targetpath) or print "Problem copying file";
}
I have written the below unit test for the same below. I tried mocking "makepath" which does not seem to work.
subtest _setup(testname => "test copyConfigFiles") => sub {
my $CONFIG = "/my/dir/with/file.xml";
my $mockfileobj = Test::MockModule->new("File::Temp", no_auto => 1);
$mockfileobj->mock('newdir', sub { return "/tmp/delme"; } );
my $amockfileobj = Test::MockModule->new("File::Path", no_auto => 1);
$amockfileobj->mock('makepath', sub { return 0; } );
lives_ok { copyConfigFiles () } 'test copyConfigFiles OK';
done_testing();
};
The problem is i am not able to mock the below lines.
make_path($targetpath) if ( ! -d $targetpath );
File::Copy::copy("$temp_dir/myfile", $targetpath) or print "Problem copying file";
Any help on how i can mock the makepath function which is perl specific? I also tried to create a temporary directory and mock the global CONFIG file with the mocked file. Didn't seem to work.
Upvotes: 2
Views: 160
Reputation: 3013
If I ignore the code that can't be run because the context is missing and focus only on the two functions that you want mocked, one can do this by temporarily replacing the sub
s in the symbol table with local
.
use warnings;
use strict;
use Data::Dump;
use File::Path qw/make_path/;
use File::Copy;
sub to_be_mocked {
my $targetpath = '/tmp/foo';
make_path($targetpath) if ! -d $targetpath;
File::Copy::copy("file.xml", $targetpath) or die;
}
sub run_with_mock {
no warnings 'redefine';
local *make_path = sub { dd 'make_path', @_; return 1 };
local *File::Copy::copy = sub { dd 'copy', @_; return 1 };
to_be_mocked();
}
run_with_mock();
__END__
# Output:
("make_path", "/tmp/foo")
("copy", "file.xml", "/tmp/foo")
Note that -d
apparently can't be mocked, at least not directly.
Upvotes: 2