http://www.perlmonks.org?node_id=413129

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

I have a subroutine f1 in a Class
Package A; use Carp; sub new { ... } sub f1 { my $param1 = shift; my $param2 = shift; my $param3 = shift; croak '- parameter1 required' unless $param1; if ((!$param2) && $param3 eq 'X') { croak '- parameter2 required' ; } some code here; }

I use Test::More to test this sub . Here is what i have used
use Test::More qw(no_plan); my $n = 1; BEGIN { use_ok('A'); } $n++; my $a = new A; isa_ok( $a,"A"); $n++; eval { $a->f1( ) }; print "ok $n"; print "\t\tno arguements passed\n"; if ( $@) { diag ( "$@\n" ); } $n++;

my question is When we do not pass parameter to the f1 then it must die,
I use eval to do this in the test script ,
Is this how i should test this function ) or is there any other option in Test::more (which is the best way)

Replies are listed 'Best First'.
Re: Test::More usage to test functions that die
by tomhukins (Curate) on Dec 08, 2004 at 14:23 UTC
Re: Test::More usage to test functions that die
by herveus (Prior) on Dec 08, 2004 at 11:44 UTC
    Howdy!

    eval sets $@ if the code dies, so something like

    ok($@, "no args passed");
    will directly test that condition.

    yours,
    Michael
Re: Test::More usage to test functions that die
by stvn (Monsignor) on Dec 08, 2004 at 15:31 UTC

    If you don't want to use Test::Exception (which I highly recommend), then the easist Test::More way of doing this would be this:

    eval { $a->f1( ) }; ok($@, '... an exception has been thrown'); like($@, qr/\- parameter1 required/, '... and it is the correct except +ion');
    I would also recomment when you test the function with parameters, to also wrap it inside an eval, like this:
    eval { $a->f1("paramter" ) }; ok(!$@, '... no exception has been thrown');
    This is the idea behind the lives_ok function in Test::Exception.

    -stvn
Re: Test::More usage to test functions that die
by trammell (Priest) on Dec 08, 2004 at 14:55 UTC
    One way is to overload croak() inside your test, then make sure that calling your function calls croak() under the right circumstances. E.g.:
    # (pseudocode) our $croakcount; sub main::croak { $croakcount++; } myfunc(my $badoptions); is ($croakcount, 1, "myfunc() calls croak()");

      This wont work unless all your code is in main:: (and even then its a delicate situation at best)

      #!/usr/bin/perl sub main::croak { print "I croaked"; } { package Test; use Carp; sub myfunc { croak("I am dying"); } } eval { Test::myfunc(); }; print $@ if $@; *myfunc = \&Test::myfunc; eval { myfunc(); }; print $@ if $@; __OUTPUT__ I am dying at test.pl line 18 I am dying at test.pl line 26
      However, what you are talking about is not unlike the ideas behind MockObjects, see Test::MockObject and Test::MockModule for more info.

      -stvn

        I know that the code as written won't work, which is why I labeled it pseudocode. But thanks for clarifying.

        Yes, this is essentially the MockObject strategy. Thanks for adding the links.