SilasTheMonk has asked for the wisdom of the Perl Monks concerning the following question:

I have a module that uses to Mail::Mailer to send out emails. Now I could really do with a test script to lock its fairly basic functionality in place. I don't want to change the code of this module at the moment as it is in use in production. I just want to build a test script around it.

I have tried using Test::MockObject and this works as far as it goes. So I can see that in my test script I can set up my mockup of Mail::Mailer in a BEGIN function. Then when I load the module under test and debug it - lo and behold the created $mailer object is a Test::MockObject rather than a Mail::Mailer. I can mock the open and close methods. The issue is that the code calls

print {$mailer} $body || croak "couldn't send whole message: $!\n";
so $mailer needs to be a GLOB reference. Fine I can pass a GLOB reference into the Test::MockObject constructor and yes the mock object is at root a GLOB reference. But I am still a lost. It is as if I have opened up a telephone exchange box and I know more or less how the cabling works, but I have lost the colour coding of the cables. Could anyone advise me how you actually connect the print cable up with the glob cable?

Replies are listed 'Best First'.
Re: How to mock Mail::Mailer
by lamprecht (Friar) on Oct 13, 2009 at 11:36 UTC
    Hi,

    maybe you could wrap Mail::Mailer::new and force the testfile backend:

    use strict; use warnings; use Mail::Mailer; package Mail::Mailer; my $basic_new; BEGIN{ $basic_new = *Mail::Mailer::new{CODE}; } sub new($@){ my @args = @_; $args[1] = 'testfile';# override type passed in use Data::Dumper; print Dumper \@args; return $basic_new->(@args); } package main; my $m = Mail::Mailer->new('smtp'); $m->open({To => 'me@here.com'}); print $m "hi\n";

    I'm not sure if this would be considered to be a sane way of doing this by the experts. So please comment if I'm suggesting something stupid...


    Cheers, Christoph

      Lamprecht,

      I don't think the idea is stupid. I have tried it and it is the closest I have got so far. In isolation it seemed to work perfectly. When I tried it in my real-life example it complained about redefining Mail::Mailer::new and the actual file was not as I expected.

      What I thought would be most likely to work to would be to take your approach of forcing a testfile and simply redefine the constructor using Test::MockObject::Extends. However I could not get that to work.

      I am sure my original approach (and perhaps the above approaches) should be workable. I will keep working on this but in the end it will simply be easiest to make my use of Mail::Mailer more configurable.