Search code examples
perltestingmojolicious

Testing a JSON PUT request in mojolicious


I am creating test cases for my app developed using Mojolicious framework. I am testing the routes for appropriate responses for the REST calls that are made. I use JSON as a means of communication between the server and client. To test GET, POST and DELETE requests I use the following functions

GET : get_ok()
POST: post_json_ok()
DELETE: delete_ok()

but for PUT I am not able to use put_ok(). And example of my usage of put_ok() would be

my $t = Test::Mojo->new;
$t->put_ok('this/is/url/to/resource'=>{ "element" => "modified value"})->status_is(204)

I get a bad request status every time(400) and so the test fails. I use Test::Mojo for testing my application.

Additional information:

$t->put_ok('http://localhost:3000/application/instances/system/test'=>{"model" => "testing put"})->status_is(204);

This is the exact test for PUT request that is attempted.
model is a property of resource test that is being attempted to be changed to testing put and the expected status response is 204.

The mapping to the controller is done by $r->route('/application/instances/system/:id, id => qr/[A-Za-z0-9 ]+/ -> via('put') ->to(controller => 'system', action => 'update_sys');
This route calls the update_sys method in the system controller and that is how the resource is located.


Solution

  • Actually, after discussions with SRI on IRC, he pointed me to an example almost identical you your needs in the documentation.

    # Test custom transaction
    my $tx = $t->ua->build_json_tx('/user/99' => {name => 'sri'});
    $tx->req->method('PUT');
    $t->tx($t->ua->start($tx))
      ->status_is(200)
      ->json_is('/message' => 'User has been replaced.');
    

    So this should work for you!

    Postscript:

    You might be interested to know that this discussion has brought some progress: the next release of Mojolicious (version 3.66) will now have a cleaner syntax for this purpose, the new request_ok method. The above example can then be rewritten as

    my $tx = $t->ua->build_json_tx('/user/99' => {name => 'sri'});
    $tx->req->method('PUT');
    $t->request_ok($tx)
      ->status_is(200)
      ->json_is('/message' => 'User has been replaced.');