Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Test streaming PSGI-based applications using AnyEvent
branch: master

Merge pull request #9 from marderh/master

add some dependencies && provides info
latest commit 9f4261b86a
Rob Hoelz authored
Failed to load latest commit information.
lib/Plack/Test Fixed issue #5
t Suppress printing of exceptions in test suite
.gitignore Initial commit
.travis.yml
Changes v0.06
README.pod Update README
dist.ini
weaver.ini Initial commit

README.pod

NAME

Plack::Test::AnyEvent - Run Plack::Test on AnyEvent-based PSGI applications

VERSION

version 0.06

SYNOPSIS

  use HTTP::Request::Common;
  use Plack::Test;

  $Plack::Test::Impl = 'AnyEvent'; # or 'AE' for short

  test_psgi $app, sub {
    my ( $cb ) = @_;

    my $res = $cb->(GET '/streaming-response');
    is $res->header('Transfer-Encoding'), 'chunked';
    $res->on_content_received(sub {
        my ( $content ) = @_;

        # test chunk of streaming response
    });
    $res->recv;
  }

DESCRIPTION

This Plack::Test implementation allows you to easily test your AnyEvent-based PSGI applications. Normally, Plack::Test::MockHTTP or Plack::Test::Server work fine for this, but this implementation comes in handy when you'd like to test your streaming results as they come in, or if your application uses long-polling. For non-streaming requests, you can use this module exactly like Plack::Test::MockHTTP; otherwise, you can set up a content handler and call $res->recv. The event loop will then run until the PSGI application closes its writer handle or until your test client calls send on the response.

FUNCTIONS

test_psgi

This function behaves almost identically to "test_psgi" in Plack::Test; the main difference is that the returned response object supports a few additional methods on top of those normally found in an HTTP::Response object:

$res->recv

Calls recv on an internal AnyEvent condition variable. Use this after you get the response object to run the event loop.

$res->send

Calls send on an internal AnyEvent condition variable. Use this to stop the event loop when you're done testing.

$res->on_content_received($cb)

Sets a callback to be called when a chunk is received from the application. A single argument is passed to the callback; namely, the chunk itself.

EXCEPTION HANDLING

As of version 0.02, this module handles uncaught exceptions thrown by your code. If the exception occurs before your PSGI application returns a response, or directly in the response subroutine ref (if you return a subroutine as your application's response), $cb will propagate the exception. Otherwise, the exception is propagated by $res->recv. Here's an example:

  my $app = sub {
    die 'thrown by $cb';

    return sub {
        my ( $respond ) = @_;

        die 'still thrown by $cb';
            
        if($streaming) {
            my $writer = $respond->([
                200,
                ['Content-Type' => 'text/plain'],
            ]);

            die 'still thrown by $cb';

            my $timer;
            $timer = AnyEvent->timer(
                after => 2,
                cb    => sub {
                    die 'thrown by $res->recv';
                    $writer->write("Ok");
                    $writer->close;
                    undef $timer;
                },
            );
        } else {
            $respond->([
                200,
                ['Content-Type' => 'text/plain'],
                ['Ok'],
            ]);

            die 'still thrown by $cb';
        }
    };
  };

  test_psgi $app, sub {
    my ( $cb ) = @_;

    my $res = $cb->(GET '/');

    $res->on_content_received(sub {
        ...
    });

    $res->recv;
  };

Note: The exception handling code may or may not work with your event loop. Please run the tests in this distribution with "PERL_ANYEVENT_MODEL" in AnyEvent set to see if it works with your event loop of choice. Patches will be accepted to accommodate loops, as long as it doesn't break known good ones. The known good event loops are:

Default
Cocoa
EV
Event
Glib
Perl

This list isn't exclusive; ie. just because your event loop isn't on this list doesn't mean it doesn't work. Also, even if your event loop doesn't pass the exception tests, the general usage of this module (testing requests, handling streaming results and long polling) should work on any AnyEvent loop. Just don't throw any uncaught exceptions =).

SEE ALSO

AnyEvent, Plack, Plack::Test

AUTHOR

Rob Hoelz <rob@hoelz.ro>

COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Rob Hoelz.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

BUGS

Please report any bugs or feature requests on the bugtracker website https://github.com/hoelzro/plack-test-anyevent/issues

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

Something went wrong with that request. Please try again.