viztastic
viztastic

Reputation: 1995

Trouble testing my Deno/Oak error handling middleware

So I have a simple middleware that listens for errors and removes details to make them friendlier:

import {
  isHttpError,
  Status,
  isProduction,
  Middleware
} from "../deps.ts";
import { Context } from "./../types.ts";

const errorMiddleware: Middleware = async (ctx: Context, next: () => Promise<unknown>) => {
  try {
    await next();
  } catch (err) {
    let message = err.message;
    const status = err.status || err.statusCode || Status.InternalServerError;

    /**
     * considering all unhandled errors as internal server error,
     * do not want to share internal server errors to 
     * end user in non "development" mode
     */
    if (!isHttpError(err)) {
      message = !isProduction
        ? message
        : "Internal Server Error";
    }

    if (!isProduction) {
      console.log(err);
    }

    ctx.response.status = status;
    ctx.response.body = { status, message };
  }
};

export { errorMiddleware };

I'm trying to write a test that throws a random error and checks to see if the middleware is adjusting the message as expected.

This is what I've tried:

Deno.test({
  name: "Middleware changes error message to Internal Server Error",
  async fn() {

    const mw1: Middleware = async (_context, next) => {
      await next();
    };
  
    let caught: any;    
    const mockContext = testing.createMockContext();
    const mockNext = () => {
      return new Promise<void>((resolve) => {
        setTimeout(() => {
          mockContext.throw(500, "Hi there");
          resolve();
        }, 50);
      });
    };

    try {
      await mw1(mockContext, mockNext); // hoping this throws the error into the next middleware
      await errorMiddleware(mockContext, testing.createMockNext());
    } catch (error) {
      caught = error;
    }

    assert(caught instanceof httpErrors.InternalServerError);
    assertEquals(caught.message,"Internal Server Error");
  },
});

The test doesn't work, I just get this error:

enter image description here

Is there a different way I should be approaching the tests? I've tried to look at the tests in the oak library to see if there's similar examples but I couldn't seem to find any.

Upvotes: 0

Views: 783

Answers (1)

jsejcksn
jsejcksn

Reputation: 33748

It's not possible to reproduce your issue because you have not provided all of the necessary code, so here's a similar, self-contained example to demonstrate how to test an error renaming middleware with Oak. Also, see the internal Oak middleware module tests for reference.

so-69820660.test.ts

import { delay } from "https://deno.land/[email protected]/async/mod.ts";
import {
  assert,
  assertEquals,
} from "https://deno.land/[email protected]/testing/asserts.ts";
import {
  composeMiddleware,
  httpErrors,
  Middleware,
  Status,
  testing,
} from "https://deno.land/x/[email protected]/mod.ts";

const renameError: Middleware = async (_, next) => {
  try {
    await next();
  } catch (exception: unknown) {
    if (!(exception instanceof Error)) throw new Error(String(exception));
    exception.message = "Custom error message";
    throw exception;
  }
};

Deno.test({
  name: "Middleware renames error message",
  async fn() {
    let exceptionWasCaught = false;

    const delayAndThrow: Middleware = async (ctx) => {
      await delay(50);
      ctx.throw(Status.InternalServerError, "Uh oh");
    };

    const catchAndAssert: Middleware = async (_, next) => {
      try {
        await next();
      } catch (exception: unknown) {
        exceptionWasCaught = true;
        assert(exception instanceof httpErrors.InternalServerError);
        assertEquals(exception.message, "Custom error message");
      }
    };

    const mw = composeMiddleware([catchAndAssert, renameError, delayAndThrow]);
    await mw(testing.createMockContext());
    assert(exceptionWasCaught);
  },
});
% deno --version
deno 1.15.3 (release, x86_64-apple-darwin)
v8 9.5.172.19
typescript 4.4.2

% deno test so-69820660.test.ts
running 1 test from file:///Users/deno/so-69820660.test.ts
test Middleware renames error message ... ok (65ms)

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (261ms)

Upvotes: 2

Related Questions