Exceptions during Mojolicious testing

By Abhijit Menon-Sen <ams@toroid.org>

2011-02-01

I've been using Test::Mojo to write tests for my Mojolicious applications, and it's great.

my $t = Test::Mojo->new(app => "Wigeon");
$t->post_form_ok('/login', {__login => $login, __passwd => $password})
    ->status_is(200)
    ->content_type_is("text/html")
    ->content_like(qr/Welcome/);
$t->get_ok('/users-only')
    ->status_is(200)
    ->content_type_is("text/html")
    ->text_is('html body p', 'First paragraph');

When something breaks (i.e., an unexpected 404 or 500 response), however, Mojolicious renders the built-in not_found or exception template, and I see the whole HTML/CSS page in my test results. Usually many times, as one failure precipitates others.

I fixed this by loading Mojolicious::Controller early in my application class and overriding its render_not_found and render_exception methods.

use Mojolicious::Controller;

...

{
    no warnings 'redefine';
    package Mojolicious::Controller;

    sub render_not_found {
        my $self = shift;
        $self->render(
            status => 404, format => 'txt',
            text => "Not found: " . $self->req->url->path
        );
    }

    sub render_exception {
        my ($self, $e) = @_;
        return if $self->stash->{'mojo.exception'};
        $self->render(
            status => 500, format => 'txt',
            handler => undef, layout => undef, extends => undef,
            text => Mojo::Exception->new($e)->message,
            "mojo.exception" => 1
        );
    }
}

Soon after I grumbled about having to do this on IRC, Sebastian Riedel added experimental support for mode-specific exception templates. One can now create stripped-down not_found.testing and exception.testing templates, and they will be automatically detected and used.