Reputation: 1995
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:
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
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