swagger-express-middleware
swagger-express-middleware copied to clipboard
Unit testing swagger-express-middleware with Jest and Supertest
Do you know how to UT a simple endpoint with Jest and Supertest when using swagger-express-middleware?
I want to unit test the very basic swagger-express-middleware walkthrough example: https://apitools.dev/swagger-express-middleware/docs/walkthroughs/walkthrough.html
But the test is not working, what is going on? I look everywhere and found no examples.
/samples/test/user.test.js
"use strict";
const app = require("./sample1.js"); // Link to your server file
const supertest = require("supertest");
const request = supertest(app);
it("gets the test endpoint", async done => {
const response = await request.get("/pet");
expect(response.status).toBe(200);
expect(response.body.message).toBe("pass!");
done();
});
/samples/package.json
{
"name": "samples",
"version": "1.0.0",
"description": "Samples & Walkthroughs ==",
"scripts": {
"start": "node sample1.js",
"test": "jest",
"test:watch": "jest --watch"
},
"dependencies": {
"swagger-express-middleware": "^2.0.5"
},
"devDependencies": {
"jest": "^25.1.0",
"supertest": "^4.0.2"
},
"author": "",
"license": "ISC"
}
/samples/sample1.js
'use strict';
const createMiddleware = require('swagger-express-middleware');
const path = require('path');
const express = require('express');
// Create an Express app
const app = express();
// Initialize Swagger Express Middleware with our Swagger file
let swaggerFile = path.join(__dirname, 'PetStore.yaml');
createMiddleware(swaggerFile, app, (err, middleware) => {
// Add all the Swagger Express Middleware, or just the ones you need.
// NOTE: Some of these accept optional options (omitted here for brevity)
app.use(
middleware.metadata(),
middleware.CORS(),
middleware.files(),
middleware.parseRequest(),
middleware.validateRequest(),
middleware.mock()
);
// Start the app
app.listen(8000, () => {
console.log('The Swagger Pet Store is now running at http://localhost:8000');
});
});
module.exports = app;
https://stackoverflow.com/questions/59852732/unit-testing-swagger-express-middleware-with-jest-and-supertest
Thanks!
createMiddleware
is loading the file asynchronously then adding the middleware after your test has run.
Instead I would recommend loading the spec file synchronously (not a performance issue since it happens once at startup) then creating your middleware like
const middleware = createMiddleware(parsedSwaggerSpec, app)
@tamlyn that's easy to tell but hard to do, thanks though!
You could create a wrapper method that returns a Promise
and resolves when the swagger middleware is ready:
const init = () =>
new Promise((resolve, reject) =>
createMiddleware(swaggerFile, app, (err, middleware) => {
if (err) {
return reject(err);
}
// do work
return resolve();
})
);
So far, I was happy testing other conventional express applications with Jest & Supertest until I got in this very same situation with swagger-middleware-express.
I've solved the way @tamlyn suggested, but it was tricky, and I had to import swagger-parser in the project explicitly. I think it will be helpful a createMiddlewareSync function shipped out of the box.
For those who are still looking for a solution, this is the code.
'use strict'
const path = require('path')
const createMiddleware = require('@apidevtools/swagger-express-middleware')
const SwaggerParser = require('@apidevtools/swagger-parser')
const express = require('express')
const app = express()
const loadSwaggerFile = async (file) => {
const swaggerFile = path.join(__dirname, file)
return SwaggerParser.dereference(swaggerFile)
}
const createSwaggerMiddlewareApp = async () => {
const parsedSwaggerSpec = await loadSwaggerFile('./api/swagger/swagger.yaml')
const middleware = createMiddleware(parsedSwaggerSpec, app)
app.use(
middleware.metadata(),
middleware.CORS(),
middleware.parseRequest(),
middleware.validateRequest(),
)
return app
}
module.exports = createSwaggerMiddlewareApp