FAQ
Hello,

Does anyone there some examples of unit tests for a controller which is based on Catalyst::Controller::REST? There was some discussion on the list a few years ago, and I think the conclusion was to use LWP directly and not Test::WWW::Mechanize::Catalyst. It seems that using the methods do not give you access to passing actual body content and content-type headers? There are getting overridden somewhere along the line. I'm going to continue to research it, but figured I'd ask here before I spend too much time on it.

Thanks,

-jr

Search Discussions

  • Bill Moseley at Dec 29, 2010 at 3:44 am

    On Tue, Dec 28, 2010 at 4:47 PM, James Russo wrote:

    Does anyone there some examples of unit tests for a controller which
    is based on Catalyst::Controller::REST? There was some discussion on the
    list a few years ago, and I think the conclusion was to use LWP directly and
    not Test::WWW::Mechanize::Catalyst. It seems that using the methods do not
    give you access to passing actual body content and content-type headers?
    There are getting overridden somewhere along the line. I'm going to continue
    to research it, but figured I'd ask here before I spend too much time on it.
    Are you asking how to make requests with specific HTTP methods (GET, PUT,
    POST, DELETE)?

    I use a module that basically does this:

    $cookie_jar->add_cookie_header( $request );
    my $cgi = HTTP::Request::AsCGI->new( $request, %ENV )->setup;
    $app_name->handle_request;
    my $response = $cgi->restore->response;
    $response->request( $request );
    $cookie_jar->extract_cookies( $response );


    where $request is an HTTP::Request. I wrap that with some utility methods
    to make creating the requests easier and to encode/decode json and set
    headers to emulate AJAX, etc.


    --
    Bill Moseley
    moseley@hank.org
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101228/df547854/attachment.htm
  • James Russo at Dec 29, 2010 at 4:03 am

    On Dec 28, 2010, at 10:44 PM, Bill Moseley wrote:
    Are you asking how to make requests with specific HTTP methods (GET, PUT, POST, DELETE)?

    I use a module that basically does this:

    $cookie_jar->add_cookie_header( $request );
    my $cgi = HTTP::Request::AsCGI->new( $request, %ENV )->setup;
    $app_name->handle_request;
    my $response = $cgi->restore->response;
    $response->request( $request );
    $cookie_jar->extract_cookies( $response );

    where $request is an HTTP::Request. I wrap that with some utility methods to make creating the requests easier and to encode/decode json and set headers to emulate AJAX, etc.

    Right. I suppose the only option is to create my own HTTP::Request object, set content and content-type header and then send it to $mech->request(...). It would be nice if post_ok() would somehow allow us to specify the actual content of the request and headers like Content-Type. As implemented right now post_ok() only allows you to specify content for form fields which are form-urlencoded into the body of the request. Would be nice to have a request_ok() method similar to the post_ok() methods which allow us to specify our own HTTP::Request objects. This would be in Test::WWW::Mechanize though..

    thanks,

    -jr



    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101228/1904ba4d/attachment.htm
  • Peter Karman at Dec 29, 2010 at 4:06 am

    James Russo wrote on 12/28/10 6:47 PM:
    Hello,

    Does anyone there some examples of unit tests for a controller which is based on Catalyst::Controller::REST? There was some discussion on the list a few years ago, and I think the conclusion was to use LWP directly and not Test::WWW::Mechanize::Catalyst. It seems that using the methods do not give you access to passing actual body content and content-type headers? There are getting overridden somewhere along the line. I'm going to continue to research it, but figured I'd ask here before I spend too much time on it.
    http://cpansearch.perl.org/src/KARMAN/CatalystX-CRUD-0.51/t/03-rest.t


    --
    Peter Karman . http://peknet.com/ . peter@peknet.com
  • James Russo at Dec 29, 2010 at 4:19 am

    On Dec 28, 2010, at 11:06 PM, Peter Karman wrote:

    James Russo wrote on 12/28/10 6:47 PM:
    Hello,

    Does anyone there some examples of unit tests for a controller which is based on Catalyst::Controller::REST? There was some discussion on the list a few years ago, and I think the conclusion was to use LWP directly and not Test::WWW::Mechanize::Catalyst. It seems that using the methods do not give you access to passing actual body content and content-type headers? There are getting overridden somewhere along the line. I'm going to continue to research it, but figured I'd ask here before I spend too much time on it.
    http://cpansearch.perl.org/src/KARMAN/CatalystX-CRUD-0.51/t/03-rest.t
    Perfect. Thanks! As Matt just pointed out on IRC, perhaps wanting to use Mech for unit testing a REST controller is a bit misguided. Catalyst::Test should be fine.

    -jr
  • James Russo at Dec 29, 2010 at 4:32 am

    On Dec 28, 2010, at 11:06 PM, Peter Karman wrote:

    James Russo wrote on 12/28/10 6:47 PM:
    Hello,

    Does anyone there some examples of unit tests for a controller which is based on Catalyst::Controller::REST? There was some discussion on the list a few years ago, and I think the conclusion was to use LWP directly and not Test::WWW::Mechanize::Catalyst. It seems that using the methods do not give you access to passing actual body content and content-type headers? There are getting overridden somewhere along the line. I'm going to continue to research it, but figured I'd ask here before I spend too much time on it.
    http://cpansearch.perl.org/src/KARMAN/CatalystX-CRUD-0.51/t/03-rest.t
    It seems the following code actually creates a request where the body of the request is the URL encoded key/values, in this case would be "content=hello%20world". Since I need to send JSON or XML data, I needed to specify the content myself, so this wouldn't work.

    # create
    ok( $res = request(
    POST( '/rest/file/testfile', [ content => 'hello world' ] )
    ),
    "POST new file"
    );


    This works as expected allowing me to specify the actual content and content-type of the request.

    # create
    ok($response = request(
    POST('/appointment','content-type' => 'application/json', 'content' => to_json($foo)
    ),
    "create new appointment"));

    Just wanted to put it out there in the archives for the next person.

    thanks,

    -jr
  • Bill Moseley at Dec 29, 2010 at 3:38 pm

    On Tue, Dec 28, 2010 at 8:32 PM, James Russo wrote:

    # create
    ok($response = request(
    POST('/appointment','content-type' =>
    'application/json', 'content' => to_json($foo)
    ),
    "create new appointment"));

    Just wanted to put it out there in the archives for the next person.
    Again, my suggestion is you put that into a test class -- you probably
    don't want to type that dozens (if not hundreds) of times. And if your
    application grows you will likely want some kind of custom test framework
    that all your test files use. And If you work with other developers it's
    helpful to have a simple test framework that's easy for everyone to use and
    understand.

    I use a generic test class that provides methods for making different types
    of request and decoding responses, provides a $schema object (as you need to
    modify data during a test), building and tearing down test data, and
    provides access to the app configuration. I can enable a debug option to
    dump full request and response and the class allows single-stepping through
    the tests. And with your REST-like methods you probably want to know more
    than than $response->is_success (which is what post_ok() checks). I then
    sub-class that for each application so I can add specific helper methods
    unique to that app.

    So, tests end up something like:

    my $test = Test::MyApp->new( debug_response => 0, dbic_trace => 0 );

    my $user = $test->create_and_login_test_user;

    $test->json_request( 201, POST => $path, \%data ); # OK if status == 201,
    and print message about request.

    my $response = $test->request( 200, GET => $path ); # $response is
    HTTP::Response sub-class.

    my $data = $response->decoded_content;
    $data->{foo} = 'bar'; # modify response data before PUT

    $test->json_request( 204, PUT => $path, $data );


    The *request methods allow passing an HTTP::Request object, too, so it's
    easy to customize a request for the rare times I need a custom header.



    --
    Bill Moseley
    moseley@hank.org
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101229/a114e3d4/attachment.htm
  • Alejandro Imass at Jan 1, 2011 at 4:16 pm

    On Tue, Dec 28, 2010 at 7:47 PM, James Russo wrote:
    Hello,

    ? ? ? ?Does anyone there some examples of unit tests for a controller which is based on Catalyst::Controller::REST? There was some >discussion on the list a few years ago, and I think the conclusion was to use LWP directly and not Test::WWW::Mechanize::Catalyst. It >seems that using the methods do not give you access to passing actual body content and content-type headers? There are getting >overridden somewhere along the line. I'm going to continue to research it, but figured I'd ask here before I spend too much time on it.
    Great discussion!

    I use HTTP::Request::Common which I have found very convenient to test
    my C::C::REST controllers, since GET, POST, PUT, etc. are exported
    into your test file, and $rs->content works as expected. We have code
    that returns both JSON and XML entities and we validate that against
    the data in the DB, using the DBIC classes directly.

    I have a small lib in my t/ directory which has a req sub that I have
    pasted below. Then each test block look something like:

    @auth = qw(
    xxxxxxxxxxxxxxxxxxxxxxx
    yyyyyyyyyyyyyyyyyyyyyyy
    );
    $rs = &req('PUT', '/xxxxx/idreq/0?test=1',
    'text/xml', 'UTF-8',
    @auth, "garbage", 'prettyxml');
    $headers = $rs->headers;
    ok($rs->code == 415, 'Validation Error on IDV')
    or diag(&dump_rs($rs));

    # get the resource from server
    if($rs->header('location') =~ m[^http://.*/xxxx/idreq/(\d+)]){
    $idreq_id = $1;
    }
    else{
    BAIL_OUT("415 test did not return location for resource. Cannot continue.");
    }
    cmp_ok($idreq_id, '>', 0, "Returned correct url for resource $1");

    $rs = &req('GET', "/xxxx/idreq/$idreq_id",
    'text/xml', 'UTF-8',
    @auth, undef, 'prettyxml');

    [... retrieve test subject xml data...]

    # see if it's really pretty xml
    cmp_ok($rs->content, 'eq', $test_xml, 'Check for Pretty XML');


    sub req {
    my $method = shift;
    my $uri = shift;
    my $type = shift;
    my $cenc = shift;
    my $authu = shift;
    my $authp = shift;
    my $content = shift;
    my $feature = shift;

    my $r;
    given($method){
    when('POST'){
    $r = POST $uri,
    Content_Type => $type,
    Content_Type_Charset => $cenc,
    Accept => $type,
    Accept_Charset => $cenc,
    Accept_Feature => $feature,
    Content => $content;
    }
    when('PUT'){
    $r = PUT $uri,
    Content_Type => $type,
    Content_Type_Charset => $cenc,
    Accept => $type,
    Accept_Charset => $cenc,
    Accept_Feature => $feature,
    Content => $content;
    }
    when('GET'){
    $r = GET $uri,
    Accept => $type,
    Accept_Charset => $cenc,
    Accept_Feature => $feature,
    }
    }

    $r->authorization_basic($authu,$authp);

    my $rs = request($r);
    return $rs;
    }




    Thanks,

    -jr
    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedDec 29, '10 at 12:47a
activeJan 1, '11 at 4:16p
posts8
users4
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase