<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>routes &amp;mdash; Simple Engineering</title>
    <link>https://getsimple.works/tag:routes</link>
    <description></description>
    <pubDate>Thu, 30 Apr 2026 13:37:44 +0000</pubDate>
    <item>
      <title>Testing expressjs Routes </title>
      <link>https://getsimple.works/testing-expressjs-routes?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[This blog post approaches testing fairly large nodejs application from a real-world perspective and with refactoring in mind. The use cases address advanced concepts that testing expressjs routes are.&#xA;&#xA;Automated testing of any JavaScript project is quite intimidating for newbies and veterans alike. &#xA;&#xA;In this article we will talk about: &#xA;&#xA;Healthy test coverage of routes&#xA;Modularization of routes for testability  &#xA;Mock Route&#39;s Request/Response Objects when necessary&#xA;Mock requests to third-party endpoints such as Payment Gateway.&#xA;&#xA;Additional challenges while testing expressjs Routes&#xA;&#xA;Test code, not the output &#xA;Mock requests to Payment Gateway, etc.&#xA;Mock database read/write operations&#xA;Be able to cover exceptions and missing data structures&#xA;&#xA;  Even though this blog post was designed to offer complementary materials to those who bought my Testing nodejs Applications book, the content can help any software developer to tuneup working environment. You use this link to buy the book.  Testing nodejs Applications Book Cover&#xA;&#xA;Show me the code&#xA;&#xA;//&#xA;var User = require(&#39;./models&#39;).User; &#xA;module.exports = function getProfile(req, res, next){&#xA;  User.findById(req.params.id, function(error, user){&#xA;    if(error) return next(error);&#xA;    return res.status(200).json(user);&#xA;  });&#xA;};&#xA;&#xA;//Router that Authentication Middleware&#xA;var router = require(&#39;express&#39;).Router();&#xA;var authenticated = require(&#39;./middleware/authenticated&#39;);&#xA;var getProfile = require(&#39;./settings/get-profile&#39;);&#xA;router.get(&#39;/profile/:id&#39;, authenticated, getProfile);&#xA;module.exports = router;&#xA;Example*:&#xA;&#xA;What can possibly go wrong?&#xA;&#xA;When (unit) test expressjs routes the following challenges may arise:&#xA;&#xA;Drawing a line between tests that fall into the unit testing category versus those tests that fall into the integration testing camp.&#xA;Being mindful that authenticated routes can appeal in the picture&#xA;Mock database read/write operations, or other layers(controller/service) that are not critical (core) to validation of the route&#39;s expectations&#xA;&#xA;Choosing tools &#xA;&#xA;  If you haven&#39;t already, reading &#34;How to choose the right tools&#34; blog post gives insights on a framework we used to choose the tools we suggest in this blog. &#xA;&#xA;Following our own Choosing the right tools framework, we suggest adopting the following tools, when testing expressjs routes: &#xA;&#xA;We can technically have auto-reload or hot-reload using: pm2, nodemon or forever. We recommend supervisor.&#xA;We can choose amongst a myriad of test runners, for instance, jasmine(jasmine-node), ava or jest. We recommend mocha. The stack mocha, chai and sinon can be worth it as well.  &#xA;supertest framework for mocking Restful APIs and nock for mocking  HTTP. &#xA;Code under test is instrumented, but default reporting tools do not always suit our every project&#39;s needs. For test coverage reporting we recommend istanbul. &#xA;&#xA;Workflow&#xA;&#xA;It is possible to generate reports as tests progress. &#xA;&#xA;  latest versions of istanbul uses nyc name.&#xA;&#xA;In package.json at &#34;test&#34; - add next line&#xA;  &#34;istanbul test mocha -- --color --reporter mocha-lcov-reporter specs&#34;&#xA;&#xA;Then run the tests using &#xA;$ npm test --coverage &#xA;&#xA;Show me the test&#xA;&#xA;  If you haven&#39;t already, read the &#34;How to write test cases developers will love&#34;&#xA;&#xA;The mainstream philosophy about automated testing is to write failing tests, followed by code that resolves the failing use cases. This is not always the case, especially when dealing with legacy code, or poorly tested code. The less puritan approach is at least tests when the code is still fresh in memory.  &#xA;&#xA;  In this article, we assume the reader knows how to mock routes, otherwise there are articles that cover the basics of mocking routes&#39; request/response objects and how to mock database read/write functions in this blog.&#xA;&#xA;The common source of frustration and sometimes bad decision-making that follows is when not able to define boundaries: when to start refactoring, and when to stop. &#xA;&#xA;Testing a route handler in isolation looks like testing any function. In our case, there should be a mocking operation of the User.findById() function, that is intended to be used with the request.  &#xA;&#xA;  For more on how to mock mongoose read/write function. &#xA;&#xA;describe(&#39;getProfile&#39;, () =  {&#xA;  let req, res, next, error;&#xA;  beforeEach(() =  {&#xA;    next = sinon.spy();&#xA;    sessionObject = { ... };//mocking session object&#xA;    req = { params: {id: 1234}, user: sessionObject };&#xA;    res = { status: (code) =  { json: sinon.spy() }}&#xA;  });&#xA;&#xA;  it(&#39;returns a profile&#39;, () =  {&#xA;    getRequest(req, res, next);&#xA;    expect(res.status().json).toHaveBeenCalled();&#xA;  });&#xA;  &#xA;  it(&#39;fails when no profile is found&#39;, () =  {&#xA;    getRequest(req, res, next);&#xA;    expect(next).toHaveBeenCalledWith([error, null]);&#xA;  });&#xA;&#xA;});&#xA;&#xA;  Please refer to this article to learn more about how to mocking mongoose read/write functions(./how-to-stub-mongoose-methods-and-mock-document-objects)). &#xA;&#xA;Testing an integral route falls into the integration testing category. Whether we connect to a live database or use a live server route is up to the programmer, but the best(fast/efficient) approach is to mock out those two expensive parts as well. &#xA;&#xA;var router = require(&#39;./profile/router&#39;),&#xA;    request = require(&#39;./support/http&#39;);&#xA;describe(&#39;/profile/:id&#39;, () =  {&#xA;  it(&#39;returns a profile&#39;, done =  {&#xA;    request(router)&#xA;      .get(&#39;/profile/12&#39;)&#xA;      .expect(200, done);&#xA;  });&#xA;&#xA;  it(&#39;fails when no profile is found&#39;, done =  {&#xA;    request(router)&#xA;      .get(&#39;/profile/NONEXISTENT&#39;)&#xA;      .expect(500, done);&#xA;  });&#xA;});&#xA;  request = require(&#39;./support/http&#39;) is the utility that may use either of supertest or dupertest provide a request.&#xA;&#xA;Conclusion&#xA;&#xA;When paying off technical debt, small bad moves can build up into catastrophe, such as downtime with little failure traceability. Good test coverage increase confidence when refactoring, refines boundaries, while at the same time reducing the introduction of new bugs in the codebase. &#xA;&#xA;In this article, we reviewed how testing tends to be more of art, than science. We also stressed the fact that, like in any art, practice makes perfect ~ testing routes, just like testing controllers, can be challenging when interacting with external systems is involved. There are additional complimentary materials in the &#34;Testing nodejs applications&#34; book. &#xA;&#xA;References&#xA;&#xA;Testing nodejs Applications book&#xA;nodejs testing essentials ~ Fred K. Schott&#xA;Testing expressjs REST APIs with mocha ~ Elliot Blog&#xA;Marcus on supertest ~ Marcus Soft Blog&#xA;&#34;How to build and test REST with nodejs Express Mocha&#34; ~ The Way of Code&#xA;A TDD Approach to Building a Todo API Using nodejs and mongodb ~ SemaphoreCI Community Tutorials&#xA;&#xA;#snippets #expressjs #routes #discuss]]&gt;</description>
      <content:encoded><![CDATA[<p>This blog post approaches testing fairly large <code>nodejs</code> application from a real-world perspective and with refactoring in mind. The use cases address advanced concepts that testing <code>expressjs</code> routes are.</p>

<p>Automated testing of any JavaScript project is quite intimidating for newbies and veterans alike.</p>

<p><strong><em>In this article we will talk about:</em></strong></p>
<ul><li>Healthy test coverage of routes</li>
<li>Modularization of routes for testability<br/></li>
<li>Mock Route&#39;s Request/Response Objects when necessary</li>
<li>Mock requests to third-party endpoints such as Payment Gateway.</li></ul>

<p>Additional challenges while testing <code>expressjs</code> Routes*</p>
<ul><li>Test code, not the output</li>
<li>Mock requests to Payment Gateway, etc.</li>
<li>Mock database read/write operations</li>
<li>Be able to cover exceptions and missing data structures</li></ul>

<blockquote><p>Even though this blog post was designed to offer complementary materials to those who bought my <strong><em><a href="https://bit.ly/2ZFJytb">Testing <code>nodejs</code> Applications book</a></em></strong>, the content can help any software developer to tuneup working environment. <strong><em><a href="https://bit.ly/2ZFJytb">You use this link to buy the book</a></em></strong>.  <a href="https://bit.ly/2ZFJytb"><img src="https://snap.as/a/42OS2vs.png" alt="Testing nodejs Applications Book Cover"/></a></p></blockquote>

<h2 id="show-me-the-code" id="show-me-the-code">Show me the code</h2>

<pre><code class="language-JavaScript">//
var User = require(&#39;./models&#39;).User; 
module.exports = function getProfile(req, res, next){
  User.findById(req.params.id, function(error, user){
    if(error) return next(error);
    return res.status(200).json(user);
  });
};

//Router that Authentication Middleware
var router = require(&#39;express&#39;).Router();
var authenticated = require(&#39;./middleware/authenticated&#39;);
var getProfile = require(&#39;./settings/get-profile&#39;);
router.get(&#39;/profile/:id&#39;, authenticated, getProfile);
module.exports = router;
</code></pre>

<p><em><em>Example</em>:</em></p>

<h2 id="what-can-possibly-go-wrong" id="what-can-possibly-go-wrong">What can possibly go wrong?</h2>

<p>When (unit) test <code>expressjs</code> routes the following challenges may arise:</p>
<ul><li>Drawing a line between tests that fall into the unit testing category versus those tests that fall into the integration testing camp.</li>
<li>Being mindful that authenticated routes can appeal in the picture</li>
<li>Mock database read/write operations, or other layers(controller/service) that are not critical (core) to validation of the route&#39;s expectations</li></ul>

<h2 id="choosing-tools" id="choosing-tools">Choosing tools</h2>

<blockquote><p>If you haven&#39;t already, reading <a href="./how-to-choose-the-right-tools.md">“How to choose the right tools”</a> blog post gives insights on a framework we used to choose the tools we suggest in this blog.</p></blockquote>

<p>Following our own <em>Choosing the right tools</em> framework, we suggest adopting the following tools, when testing <code>expressjs</code> routes:</p>
<ul><li>We can technically have auto-reload or hot-reload using: <code>pm2</code>, <code>nodemon</code> or <code>forever</code>. We recommend <code>supervisor</code>.</li>
<li>We can choose amongst a myriad of test runners, for instance, <code>jasmine</code>(<code>jasmine-node</code>), <code>ava</code> or <code>jest</code>. We recommend <code>mocha</code>. The stack <code>mocha</code>, <code>chai</code> and <code>sinon</code> can be worth it as well.<br/></li>
<li><code>supertest</code> framework for mocking Restful APIs and <code>nock</code> for mocking  HTTP.</li>
<li>Code under test is instrumented, but default reporting tools do not always suit our every project&#39;s needs. For test coverage reporting we recommend <code>istanbul</code>.</li></ul>

<h2 id="workflow" id="workflow">Workflow</h2>

<p>It is possible to generate reports as tests progress.</p>

<blockquote><p>latest versions of <code>istanbul</code> uses <code>nyc</code> name.</p></blockquote>

<pre><code class="language-shell"># In package.json at &#34;test&#34; - add next line
&gt; &#34;istanbul test mocha -- --color --reporter mocha-lcov-reporter specs&#34;

# Then run the tests using 
$ npm test --coverage 
</code></pre>

<h2 id="show-me-the-test" id="show-me-the-test">Show me the test</h2>

<blockquote><p>If you haven&#39;t already, read the <a href="./how-to-write-test-cases-developers-will-love.md">“How to write test cases developers will love”</a></p></blockquote>

<p>The mainstream philosophy about automated testing is to write failing tests, followed by code that resolves the failing use cases. This is not always the case, especially when dealing with legacy code, or poorly tested code. The less puritan approach is at least tests when the code is still fresh in memory.</p>

<blockquote><p>In this article, we assume the reader knows how to mock routes, otherwise there are articles that cover the basics of <a href="./how-to-stub-http-requests">mocking routes&#39; request/response objects</a> and <a href="./how-to-stub-mongoose-methods-and-mock-document-objects">how to mock database read/write functions</a> in this blog.</p></blockquote>

<p>The common source of frustration and sometimes bad decision-making that follows is when not able to define boundaries: when to start refactoring, and when to stop.</p>

<p>Testing a route handler in isolation looks like testing any function. In our case, there should be a mocking operation of the <code>User.findById()</code> function, that is intended to be used with the request.</p>

<blockquote><p>For more on <a href="./how-to-stub-mongoose-methods-and-mock-document-objects">how to mock mongoose read/write function</a>.</p></blockquote>

<pre><code class="language-JavaScript">describe(&#39;getProfile&#39;, () =&gt; {
  let req, res, next, error;
  beforeEach(() =&gt; {
    next = sinon.spy();
    sessionObject = { ... };//mocking session object
    req = { params: {id: 1234}, user: sessionObject };
    res = { status: (code) =&gt; { json: sinon.spy() }}
  });

  it(&#39;returns a profile&#39;, () =&gt; {
    getRequest(req, res, next);
    expect(res.status().json).toHaveBeenCalled();
  });
  
  it(&#39;fails when no profile is found&#39;, () =&gt; {
    getRequest(req, res, next);
    expect(next).toHaveBeenCalledWith([error, null]);
  });

});
</code></pre>

<blockquote><p>Please refer to this article to learn more about <a href="](./how-to-stub-mongoose-methods-and-mock-document-objects)">how to mocking mongoose read/write functions</a>.</p></blockquote>

<p>Testing an integral route falls into the integration testing category. Whether we connect to a live database or use a live server route is up to the programmer, but the best(fast/efficient) approach is to mock out those two expensive parts as well.</p>

<pre><code class="language-JavaScript">var router = require(&#39;./profile/router&#39;),
    request = require(&#39;./support/http&#39;);
describe(&#39;/profile/:id&#39;, () =&gt; {
  it(&#39;returns a profile&#39;, done =&gt; {
    request(router)
      .get(&#39;/profile/12&#39;)
      .expect(200, done);
  });

  it(&#39;fails when no profile is found&#39;, done =&gt; {
    request(router)
      .get(&#39;/profile/NONEXISTENT&#39;)
      .expect(500, done);
  });
});
</code></pre>

<blockquote><p> <code>request = require(&#39;./support/http&#39;)</code> is the utility that may use either of <code>supertest</code> or <code>dupertest</code> provide a request.</p></blockquote>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>When paying off technical debt, small bad moves can build up into catastrophe, such as downtime with little failure traceability. Good test coverage increase confidence when refactoring, refines boundaries, while at the same time reducing the introduction of new bugs in the codebase.</p>

<p>In this article, we reviewed how testing tends to be more of art, than science. We also stressed the fact that, like in any art, practice makes perfect ~ testing routes, just like testing controllers, can be challenging when interacting with external systems is involved. There are additional complimentary materials in the <strong>“Testing <code>nodejs</code> applications”</strong> book.</p>

<h2 id="references" id="references">References</h2>
<ul><li><a href="https://bit.ly/2ZFJytb">Testing <code>nodejs</code> Applications book</a></li>
<li><code>nodejs</code> testing essentials ~ <a href="https://fredkschott.com/post/2014/05/nodejs-testing-essentials/">Fred K. Schott</a></li>
<li>Testing <code>expressjs</code> REST APIs with <code>mocha</code> ~ <a href="https://51elliot.blogspot.ca/2013/08/testing-expressjs-rest-api-with-mocha.html">Elliot Blog</a></li>
<li>Marcus on <code>supertest</code> ~ <a href="https://www.marcusoft.net/2014/02/mnb-supertest.html">Marcus Soft Blog</a></li>
<li><em>“How to build and test REST with <code>nodejs</code> Express Mocha”</em> ~ <a href="https://thewayofcode.wordpress.com/2013/04/21/how-to-build-and-test-rest-api-with-nodejs-express-mocha/">The Way of Code</a></li>
<li>A TDD Approach to Building a Todo API Using <code>nodejs</code> and <code>mongodb</code> ~ <a href="https://semaphoreci.com/community/tutorials/a-tdd-approach-to-building-a-todo-api-using-node-js-and-mongodb">SemaphoreCI Community Tutorials</a></li></ul>

<p><a href="https://getsimple.works/tag:snippets" class="hashtag"><span>#</span><span class="p-category">snippets</span></a> <a href="https://getsimple.works/tag:expressjs" class="hashtag"><span>#</span><span class="p-category">expressjs</span></a> <a href="https://getsimple.works/tag:routes" class="hashtag"><span>#</span><span class="p-category">routes</span></a> <a href="https://getsimple.works/tag:discuss" class="hashtag"><span>#</span><span class="p-category">discuss</span></a></p>
]]></content:encoded>
      <guid>https://getsimple.works/testing-expressjs-routes</guid>
      <pubDate>Thu, 17 Jun 2021 00:19:52 +0000</pubDate>
    </item>
  </channel>
</rss>