Re-re-re-re-factor

Being able to safely refactor code is one of the greatest benefits of writing tests. The goal of refactoring is to improve code design e.g. style, design patterns, performance.

Let's take an example from the previous route handler which has already been refactored.

import fastify from 'fastify';

// for testing
export async function start(options: { port: number }) {
  const server = fastify({ logger: true });

  // basic health response can be anything
  server.get('/health', async () => 'OK');
  const { port } = options;

  await server.listen(port);

  return server;
}

// so we can node ./build/index.js to start the server
(async () => start({ port: Number(process.env.PORT) }))();

The minimum required to pass the test is

(async () => { 
  const server = fastify();

  await server.get('/health', async () => 'OK')
  await server.listen(4000);

  return server;
 })();

But the issue with this version of the code is this error:

 FAIL  src/index.test.ts (7.241 s)
  Given start
    ✕ Server is listening (5002 ms)

  ● Given start › Server is listening

    connect ECONNREFUSED 127.0.0.1:4000



  ● Given start › Server is listening

    thrown: "Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

By using a fixed port number the server under test has trouble being started and stopped.

The solution to this would be to randomise the port number. The issue is the test runner would need to know where the server is listening. We solve this by using Inversion of Control and giving the server under test the port to listen on. 👂🏽

export async function start(options: { port: number }) {
  const server = fastify();
  const { port } = options;

  await server.get('/health', async () => 'OK')
  await server.listen(port);


  return server;
}

It's a good habit to refactor tests and the code under tests separately. By writing our tests first, we can be more confident when we make changes.

Martin Fowler goes into a lot more detail in his book on Refactoring. 🔧