perltestingintegration-testingdie

What is the easiest way to test error handling when writing to a file in Perl?


I have a bog standard Perl file writing code with (hopefully) adequate error handling, of the type:

open(my $fh, ">", "$filename") or die "Could not open file $filname for writing: $!\n";
# Some code to get data to write
print $fh $data  or die "Could not write to file $filname: $!\n";
close $fh  or die "Could not close file $filname afterwriting: $!\n";
# No I can't use File::Slurp, sorry.

(I just wrote this code from memory, pardon any typos or bugs)

It is somewhat easy to test error handling in the first "die" line (for example, create a non-writable file with the same name you plan to write).

How can I test error handling in the second (print) and third (close) "die" lines?

The only way I know of to induce error when closing is to run out of space on filesystem while writing, which is NOT easy to do as a test.

I would prefer integration test type solutions rather than unit test type (which would involve mocking IO methods in Perl).


Solution

  • Working with a bad filehandle will make them both fail

    use warnings;
    use strict;
    use feature 'say';
    
    my $file = shift || die "Usage: $0 out-filename\n";
    
    open my $fh, '>', $file  or die "Can't open $file: $!";
    
    $fh = \*10;
    
    say $fh 'writes ok, ', scalar(localtime)  or warn "Can't write: $!";
    
    close $fh or warn "Error closing: $!";
    

    Prints

    say() on unopened filehandle 10 at ...
    Can't write: Bad file descriptor at ...
    close() on unopened filehandle 10 at ...
    Error closing: Bad file descriptor at ...
    

    If you don't want to see perl's warnings capture them with $SIG{__WARN__} and print your messages to a file (or STDOUT), for example.