Acme-CPANModulesBundle-Import-PerlDancerAdvent-2018

 view release on metacpan or  search on metacpan

devdata/http_advent.perldancer.org_2018_20  view on Meta::CPAN

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title> Testing Dancer with Test::Mojo | PerlDancer Advent Calendar</title>
<link rel="stylesheet" href="/css/style.css" />
<link rel="alternate" type="application/rss+xml" title="All Articles " href="/feed/2018" /> 


<!-- Grab Google CDN's jQuery. fall back to local if necessary -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">/* <![CDATA[ */
    !window.jQuery && document.write('<script src="/javascripts/jquery.js"><\/script>')
/* ]]> */</script>

<!-- Prettyfy -->
<link href="/css/prettify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="/javascripts/prettify.js"></script>

</head>
<body onload="prettyPrint()">
<div id="page">

<div id="sidebar">
<a href="/" class="homelink">Dancer Advent Calendar</a><br />

<p>
The PerlDancer Advent Calendar is a community-driven project that aims 
to showcase the Dancer Perl web framework.
</p>

<p>
Each day of December until Christmas, one article about Dancer. Stay tuned for new moves!
</p>

<ul id="sidebar-items">
<li>
    <h3>About Dancer</h3>
    <ul class="links">
        <li><a href="http://www.perldancer.org/">Dancer homepage</a></li>
        <li><a href="http://twitter.com/PerlDancer">Official Twitter</a></li>
        <li><a href="http://github.com/PerlDancer/Dancer">Dancer on GitHub</a></li>
        <li><a href="http://github.com/PerlDancer/Dancer2">Dancer 2 on GitHub</a></li>
        <li><a class="feed" href="/feed/2018">RSS</a></li>
    </ul>
</li>
</ul>
</div>


<div id="content">
<div class="pod-document"><h1><a name="testing_dancer_with_test__mojo"></a>Testing Dancer with Test::Mojo</h1>

<p>Authors of Dancer (and other) PSGI applications are probably accustomed to <a href="https://metacpan.org/pod/distribution/Dancer2/lib/Dancer2/Manual.pod#TESTING">testing</a> with <a href="https://metacpan.org/pod/Plack::Test">Plack::Test</a>, and ...
<p>During advent last year, I wrote about <a href="https://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>, showing the many easy and (dare I say) fun ways that you can use it to test your Mojolicious applications.
If you missed it, go <a href="https://mojolicious.io/blog/2017/12/09/day-9-the-best-way-to-test/">check it out</a>.</p>
<p>I expect there are at least a few of you out there who read that and think, "I'd love to use that, but I don't use Mojolicious!"; well, you're in luck!
With just a little role to bridge the gap, you can use Test::Mojo to test your PSGI applications too!</p>
<h2><a name="mounting_psgi_applications"></a>Mounting PSGI Applications</h2>

<p>Mojolicious itself doesn't use the <a href="https://metacpan.org/pod/PSGI">PSGI</a> protocol, owing to certain features that it doesn't provide and which are necessary for certain asynchronous operations.
That said, you can serve a Mojolicious application on a PSGI server by using <a href="https://mojolicious.org/perldoc/Mojo/Server/PSGI">Mojo::Server::PSGI</a>.
This Mojolicious-core module is automatically used for you when your Mojolicious-based app detects that it has started under a PSGI server (e.g. plackup or Starman).</p>
<p>While translating between a Mojo app and a PSGI server is core functionality, doing the opposite, translating between a PSGI app and a Mojolicious server (or app, as you'll see) is available as a third party module.
<a href="https://metacpan.org/pod/Mojolicious::Plugin::MountPSGI">Mojolicious::Plugin::MountPSGI</a>, as it's name implies, can mount a PSGI application into a Mojolicious-based one.
To do so, it builds a new, empty Mojolicious application that translates all requests to PSGI environments before dispatching to it as with any <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/Mount">mount</a>-ed application.</p>
<h2><a name="testing_using_test__mojo"></a>Testing using Test::Mojo</h2>

<p>Once you can do that, it is trivial to take a PSGI application, wrap it with MountPSGI, and set it as the application for use with Test::Mojo.
Still, to make it even easier, that has all been done for you in <a href="https://metacpan.org/pod/Test::Mojo::Role::PSGI">Test::Mojo::Role::PSGI</a>.</p>
<p>Like any <a href="https://mojolicious.io/blog/2017/12/13/day-13-more-about-roles/">Mojolicious Role</a>, we can use <code>with_roles</code> to create a (mostly anonymous) subclass with the role applied.
You can use the shortcut <code>+</code> to stand in for <code>Test::Mojo::Role::</code>.</p>
<pre class="prettyprint">use Test::Mojo;
my $class = Test::Mojo-&gt;with_roles('+PSGI');</pre>

<p>Then you instantiate that role with the path to the PSGI application, or else the PSGI application itself.</p>
<p>Since you're using roles, which are all about composition, you can also apply other roles that you might <a href="https://metacpan.org/search?q=%22Test%3A%3AMojo%3A%3ARole%22">find on CPAN</a>.</p>
<h2><a name="an_example"></a>An Example</h2>

<p>As an example, let's say we have a simple application script (named <code>app.psgi</code>) that can render a <code>"hello world"</code> or <code>"hello $user"</code> in several formats.
I'll allow a plain text response, JSON, and templated HTML (using the <a href="https://metacpan.org/pod/Dancer2::Template::Simple">simple</a> template to keep this concise).</p>
<pre class="prettyprint">use Dancer2;

set template =&gt; 'simple';
set views =&gt; '.';

any '/text' =&gt; sub {
  my $name = param('name') // 'world';
  send_as plain =&gt; "hello $name";
};

any '/data' =&gt; sub {
  my $name = param('name') // 'world';
  send_as JSON =&gt; { hello =&gt; $name };
};

any '/html' =&gt; sub {
  my $name = param('name') // 'world';
  template 'hello' =&gt; { name =&gt; $name };
};

start;</pre>

<p>And the template (<code>hello.tt</code>) is</p>
<pre class="prettyprint">&lt;dl id="data"&gt;
  &lt;dt id="hello"&gt;hello&lt;/dt&gt;
  &lt;dd&gt;&lt;% name %&gt;&lt;/dd&gt;
&lt;/dl&gt;</pre>

<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl">dl</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt">dt</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd">dd</a> tags...
The HTML I've built, while nice for display isn't necessarily nice for querying programmatically, this is on purpose for the example.</p>
<h2><a name="the_tests"></a>The Tests</h2>

<p>Of course we could start the application with <a href="https://metacpan.org/pod/distribution/Plack/script/plackup">plackup</a> but that's not what we're trying to do.
I'll break the test script down a bit but if you want to see any of these files look at the <a href="https://github.com/MojoliciousDotIO/mojolicious.io/tree/master/blog/2018/12/20/testing-dancer/ex">blog repo</a> for a full listing.
Instead, let's load this into a test script.</p>



( run in 0.541 second using v1.01-cache-2.11-cpan-39bf76dae61 )