I’m encountering a 500 Internal Server Error when running a Jest test for my Express app using Supertest, but the app works fine when run normally (e.g., in a browser or Postman). I suspect the issue lies in the test setup, but I’m unable to pinpoint the exact cause.
This is the error message when running npm test
$ npm test
> [email protected] test
> cross-env NODE_OPTIONS=--experimental-vm-modules jest
(node:16440) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
FAIL tests/movies.test.js
Ă— Home page shows list of movies and navigation links (31 ms)
â—Ź Home page shows list of movies and navigation links
expected 200 "OK", got 500 "Internal Server Error"
33 | );
34 |
> 35 | const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);
| ^
36 |
37 | expect(response.text).toMatch('Pulp Fiction');
38 | expect(response.text).toMatch('Fire Walk With Me');
at Object.expect (tests/movies.test.js:35:79)
----
at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
at node_modules/supertest/lib/test.js:308:13
at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
at Test.assert (node_modules/supertest/lib/test.js:164:23)
at Server.localAssert (node_modules/supertest/lib/test.js:120:14)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.617 s, estimated 1 s
Ran all test suites.
I’ll provide some of my code
movies.test.js
import { expect, test } from '@jest/globals';
import request from 'supertest';
import { fetchAllMovies, fetchMovie } from '../src/js/server/fetchMovies.js';
import startApp from '../src/js/server/app.js';
test('Home page shows list of movies and navigation links', async () => {
const app = startApp(
{
fetchMovie: async () => ({
id: 1,
title: 'Pulp Fiction',
}),
fetchAllMovies: async () => [
{ id: 1, title: 'Pulp Fiction' },
{ id: 2, title: 'Fire Walk With Me' },
{ id: 3, title: 'Isle of Dogs' },
],
},
{
navLinks: async () => ({
headerData: [
{ label: 'BILJETTER', id: 'biljetter', link: '#' },
{ label: 'EVENEMANG', id: 'evenemang', link: '#' },
{ label: 'FILMER', id: 'filmer', link: 'movies' },
],
footerSection1: [
{ label: 'OM KINO', link: 'about' },
{ label: 'FRĂ…GOR SVAR', link: '#' },
{ label: 'KONTAKTA OSS', link: '#' },
],
}),
}
);
const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);
expect(response.text).toMatch('Pulp Fiction');
expect(response.text).toMatch('Fire Walk With Me');
expect(response.text).toMatch('Isle of Dogs');
expect(response.text).toMatch('BILJETTER');
expect(response.text).toMatch('EVENEMANG');
expect(response.text).toMatch('FILMER');
});
server.js
import startApp from './src/js/server/app.js';
import { fetchAllMovies, fetchMovie } from './src/js/server/fetchMovies.js';
import navLinks from './src/js/server/navLinks.js';
const api = {
fetchMovie,
fetchAllMovies,
};
const nav = {
navLinks,
};
const app = startApp(api, nav);
const PORT = process.env.PORT || 5080;
app.listen(5080, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
app.js
import express from 'express';
import ejs from 'ejs';
import { marked } from 'marked';
function startApp(api, nav) {
const app = express();
app.locals.formatMarkdown = (text) => marked(text);
app.set('view engine', 'ejs');
app.get('/', async (req, res) => {
const linkData = await nav.navLinks();
const moviesData = await api.fetchAllMovies();
res.render('pages/index', { moviesData, ...linkData });
});
app.get('/movies', async (req, res) => {
const linkData = await nav.navLinks();
const moviesData = await api.fetchAllMovies();
res.render('pages/allMovies', { moviesData, ...linkData });
});
app.get('/movie/:movieId', async (req, res) => {
const linkData = await nav.navLinks();
const movieData = await api.fetchMovie(req.params.movieId);
res.render('pages/movie', { movieData, ...linkData });
});
app.use('/static', express.static('./static'));
app.use((req, res) => {
const linkData = nav.navLinks();
res.status(404).render('pages/error', { message: 'Page not found', ...linkData });
});
return app;
}
export default startApp;
navLinks.js
const headerData = [
{
label: 'BILJETTER',
id: 'biljetter',
link: '#',
},
{
label: 'EVENEMANG',
id: 'evenemang',
link: '#',
},
{
label: 'FILMER',
id: 'filmer',
link: 'movies',
},
{
label: 'MEDLEMSKAP',
id: 'medlemskap',
link: '#',
},
{
label: 'OM OSS',
id: 'omoss',
link: 'about',
},
];
const footerSection1 = [
{ label: 'OM KINO', link: 'about' },
{ label: 'FRĂ…GOR SVAR', link: '#' },
{ label: 'KONTAKTA OSS', link: '#' },
];
const footerSection2 = [
{ label: 'PRESENTKORT', link: '#' },
{ label: 'TILLGÄNGLIGHET', link: '#' },
{ label: 'MEDLEMSKAP', link: '#' },
{ label: 'BISTRO-BIO', link: '#' },
{ label: 'EVENEMANG', link: '#' },
];
const footerSection3 = [
{ label: 'FACEBOOK', link: '#' },
{ label: 'INSTAGRAM', link: '#' },
];
export default function navLinks() {
return {
headerData,
footerSection1,
footerSection2,
footerSection3,
};
}
- Run the app normally: When I start the app and visit http://localhost:5080 in my browser, it works fine. I see the movie list as expected.
- Added logging: I added a global error handler and logged the error, but the error is not logged in the console during the test.
- Mock data: I confirmed that the mocked fetchAllMovies is being called and returns the correct data.
- Simplified test: I replaced the test with a basic request to ‘/’ with no expectations or assertions, but the 500 error persists.