Hi Monks,

I want to mock files in my tests. I could not find any module that could help. So I wrote my own: Test::MockInputFile.

However, I had a couple of problems:
. I was able to mock files only for reading. Because I cannot override the print builtin.
. I could not use a bareword as a file handler in the open and close builtins. This is most probably due to my lack of knowledge on globs and prototypes.

I have the following questions on this subject:
. Is there already a module which does this job?
. Is the module I have written worth putting on CPAN?
. Do you have any suggestions on the problems I face?

package Test::MockInputFile; use strict; # --- my %file; sub define_file_mocker { my ($name, $content) = @_; $content ||= ''; $file{$name} = $content; } sub undefine_file_mocker { my ($name, $content) = @_; delete $file{$name}; } # --- sub import { my ($class, %arg) = @_; my $package = caller; _export_functions_to($package); my $module = defined $arg{module} ? $arg{module} : $package; _override_open_and_close_builtins_for($module); } # --- sub _export_functions_to { my ($package) = @_; no strict 'refs'; *{"$package\::define_file_mocker"} = \&define_file_mocker; *{"$package\::undefine_file_mocker"} = \&undefine_file_mocker; } # --- sub _override_open_and_close_builtins_for { my ($module) = @_; no strict 'refs'; *{"$module\::open"} = sub (\$$;$) { my ($fh, $mode, $name) = @_; if ($mode =~ /^<$/) { } elsif ($mode =~ /^<\s*([^<>].*)$/) { $name = $1; } else { $name = $mode; } # --- if (! defined $file{$name}) { # indicating; 'No such file or directory' $! = 2; return 0; } $$fh = Test::MockInputFile::Handler->new($name); return 1; }; *{"$module\::close"} = sub (\$) { my ($fh) = @_; undef $$fh; }; } # --- { package Test::MockInputFile::Handler; use overload '<>' => \&next_line; sub new { my ($class, $name) = @_; bless { content => $file{$name}, }, $class; } sub next_line { my ($self) = @_; if (! defined $self->{content}) { return undef; } my $line; if (! defined $/) { $line = $self->{content}; $self->{content} = undef; } elsif ($self->{content} =~ m;(.+?$/);s) { $line = $1; $self->{content} = $'; $self->{content} = undef if $self->{content} eq ''; } else { $line = $self->{content}; $self->{content} = undef; } return $line; } } # --- 1;
Thanks,
Oguz

---------------------------------
life is ... $mutation = sub { $_[0] =~ s/(.)/rand()<0.1?1-$1:$1/ge };


In reply to Mocking files for reading by mayaTheCat

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.