in reply to Re^2: Can I catch a die from someone else's module?
in thread Can I catch a die from someone else's module?

Do I need the 1; ?

Generally, yes, you should include it. The reason is that eval returns undef on failure, which is what the or do { ... } is intended to react to. However, the or would also be triggered if the eval block were to return any other false value, such as 0 or the empty string. For example, the following incorrectly prints "Error from Module::That::Dies:". So unless you can be absolutely sure that the eval block always returns a true value, you should include the 1 (or any other true value) as the last statement of the block.

sub Module::That::Dies::die_here { return 0 } eval { Module::That::Dies::die_here(); #1; } or do { warn "Error from Module::That::Dies:\n$@\n"; };

Update: I tend to write it like the following, since the 1 on a line by itsself can look out of place and might be accidentally deleted:

eval { ... ;1 } or do { # catch ... }

Replies are listed 'Best First'.
Re^4: Can I catch a die from someone else's module?
by stevieb (Canon) on Apr 19, 2022 at 19:29 UTC

    I, too, use the eval { ...; 1; };. I'm literally just writing unit tests with eval right now, so I thought I'd share how I often write them:

    my $missing_opt_code_succeeded = eval { $tesla->option_codes('NON_EXIST'); 1; }; is $missing_opt_code_succeeded, undef, "If an option code doesn't exist, we croak ok"; like $@, qr/does not exist/, "...and error message is sane";

      G'day stevieb,

      It's your module and you can test it in whatever way you want; however, I'd have a problem with the separation of the eval block and $@ several lines later.

      Here's a real-world ($work) example I wrote a few years ago that similarly tests for failure. In this instance, it checks that an abstract class can't be instantiated. I just grabbed it from git and only changed the class name to Abstract::Work::Class; otherwise, this is a verbatim copy of 01-abstract.t:

      #!perl -T use 5.016; use warnings; use Test::More tests => 3; use Abstract::Work::Class; my $obj; my $no_instantiation = 0; my $eval_message = ''; eval { $obj = Abstract::Work::Class::->new(); 1; } or do { $eval_message = $@; $no_instantiation = 1; }; ok(! defined($obj), 'Test potential object remains undefined'); ok($no_instantiation, 'Test no instantiation of abstract class'); ok(index($eval_message, 'FATAL! Attempt to instantiate an abstract cla +ss.') == 0, 'Test error message from attempting instantiation of abstract clas +s');

      I normally attempt to capture the value of $@ as the first statement in '... or do { ... };'.

      As a testament to the robustness of that code, it's from one of the core modules of a large 30+ module framework. The framework has been modified, extended and enhanced many times, and built on many platforms, over the last four years; 01-abstract.t was last modified in May 2018. It's a solid solution and you're welcome to adapt it to your needs if you want.

      — Ken