I'm currently facing a challenge in writing an integration test for my express router using typescript, mocha, sinon, and chai-http. The router incorporates a custom middleware I created to validate JWT tokens present in the header.
My goal is to mock the authMiddleware
so that I can manipulate its behavior without needing to provide valid or invalid JWT tokens for each test case.
However, when attempting to stub the authMiddleware
in my tests, I discovered that the express app
was utilizing the actual implementation of the middleware instead of the mocked version.
I even tried importing the app
after mocking the authMiddleware
with dynamic imports in typescript, but unfortunately, it didn't yield the desired outcome either.
authMiddleware.ts
import { Request, Response, NextFunction } from 'express';
export default class AuthMiddleware {
verifyToken(req: Request, res: Response, next: NextFunction) :void {
console.log('Actual implemetation of verifyToken is called!');
// verify token
next();
}
}
subjectRouter.ts
import express from'express';
import AuthMiddleware from '../middleware/authMiddleware';
import * as subjectController from '../controller/subjectController';
const router = express.Router();
const authMiddleware = new AuthMiddleware();
router.post('/', authMiddleware.verifyToken, subjectController.createSubject);
export default router;
app.ts
import express from 'express';
import subjectRoute from './route/subjectRoute';
// Initilize express app
const app = express();
app.set("port", 3000);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Routers
app.use('/user', userRoute);
app.use('/subject', subjectRoute);
export default app;
subjectTests.ts
import app from '../../src/app';
import AuthMiddleware from '../../../src/middleware/AuthMiddleware';
describe('Subject', () => {
let app;
beforeEach(async () => {
sinon.stub(AuthMiddleware.prototype, 'verifyToken').callsFake((req: Request, res: Response, next: NextFunction): void => {
console.log('Fake verifyToken is called!');
// THIS IS NEVER CALLED IN TESTS...
});
app = (await import('../../../src/app')).default;
});
it('should throw 403 when jwt is missing in header', (done) => {
request(app)
.post(/subject)
.end((err, res) => {
expect(res).has.status(403);
done();
});
});
});
Upon running the above test, I noticed that the mocked authMiddleware
wasn't being invoked. Instead, the app
in the tests continued to leverage the original implementation of the authMiddleware
object.
Is there a method to effectively stub express middleware and explicitly pass it to the app?