Open yegorkay opened 4 years ago
These two can help https://www.npmjs.com/package/light-my-request or https://www.npmjs.com/package/supertest
Using the above, you don't have to start and close the server.
Thanks for the reply! I tried setting up a test for the file mentioned above, and realize it's the database and session middlewares causing the 500
error. 200
happens when you comment both of them out of here. You would then have to change the endpoint to not use Mongo like so to pass the test since the middleware isn't applied:
import nextConnect from 'next-connect';
import middleware from '../../../../middlewares/middleware';
import { getUser } from '../../../../lib/db';
const handler = nextConnect();
handler.use(middleware);
// dumb API without mongo
handler.get(async (req, res) => {
res.send(`hello ${req.query.userId}`);
});
export default handler;
// working test, assuming no Mongo middleware applied
import http from 'http'
import fetch from 'isomorphic-unfetch'
import listen from 'test-listen'
import { apiResolver } from 'next/dist/next-server/server/api-utils'
import handler from '.';
const USER_ID = 'SOME_ID' // to be an actual id once 500 is resolved
describe(`/users/${USER_ID}`, () => {
test('responds 200', async () => {
const requestHandler = (req, res) => apiResolver(req, res, undefined, handler)
const server = http.createServer(requestHandler)
const url = await listen(server)
const response = await fetch(`${url}/${USER_ID}`)
expect(response.status).toBe(200)
return server.close()
})
})
Seems like this issue doesn't pertain to this repo, but more towards the nextjs-mongo-db-app
repo. I can move this there. I've been trying to figure out how to get integration testing to work there, but I haven't been getting very far. Any ideas as to why mongo causes this to fail?
Oh I see. This should have been mentioned clearer in next-connect
doc. next-connect
does not add anything by default so things like query parsing (req.query
) and helpers like (res.send
) are not available. That why errors were thrown in your case.
Nope, wrong assumption, you are using apiResolver
so it should work. Did you manage to get the error message?
Still getting a 500 sadly. Here are the changes I made if you want to see what's going on:
https://github.com/yegorkay/nextjs-mongodb-app/tree/feature/testing
@yegorkay hey sorry I didn't check in here for a while - I have a whole testing setup tailored for nextjs here: https://github.com/ljosberinn/personal-react-boilerplate/blob/master/testUtils/lambda.ts
and a few tests: https://github.com/ljosberinn/personal-react-boilerplate/tree/master/src/server/__tests__
My approach to test is https://github.com/leosuncin/literate/blob/master/tests/pages/api/auth/register.spec.ts
I use @shelf/jest-mongodb to run MongoDB in-memory, but basically I use node-mocks-http to mock req
and res
objects
Another idea is to use supertest
import http from 'http';
import { apiResolver } from 'next/dist/next-server/server/api-utils';
import supertest from 'supertest';
import registerHandler from 'pages/api/auth/register';
jest.setTimeout(10e3);
describe('[POST] /api/auth/register', () => {
let server;
beforeEach(async () => {
const requestHandle = (request, response) =>
apiResolver(
request,
response,
undefined,
registerHandler,
{},
true,
);
server = http.createServer(requestHandler);
});
afterEach(() => {
server.close();
});
it('creates a new user', async () => {
const body = {
name: 'John Doe',
email: 'johndoe@example.com',
password: 'ji32k7au4a83',
};
const result = await supertest(server)
.post('/api/auth/register')
.send(body)
.expect(201)
.expect('Content-Type', /json/);
expect(result.body).toBeDefined();
});
it.each([
{
name: '',
email: '',
password: '',
},
{
name: 'a',
email: 'email',
password: '123456',
},
])('validate the body %p', async (body) => {
const result = await supertest(server)
.post('/api/auth/register')
.send(body)
.expect(422)
.expect('Content-Type', /json/);
expect(result.body).toBeDefined();
});
});
It has the advantage of no need to start a server
node-mocks-http
.You can use #166 branch like this
npm i --save https://github.com/jakeorr/next-connect#c837eee
and add "postinstall" script to package.json
{
"scripts": {
"postinstall": "cd node_modules/next-connect; npm i; npm run build"
}
}
Is there a way to test with Jest?
This isn't my post but it is the same issue I'm facing: https://stackoverflow.com/questions/67961149/how-do-i-test-a-next-js-api-route-which-uses-next-connect
When using next-connect
I get a timeout error. When using without, the tests work as expected.
Cheers!
@nath-green I use next-connect and using leosuncin's solution worked for me. It no longer has the jest timeout issue
If someone need some guidance about how to write unit-tests (with Jest) for your middlewares, I've written a blog-post about it.
If you need to test an API route endpoint from end-to-end, I recommend using next-test-api-route-handler (ntarh)
I suggest you to use this pacakge: https://www.npmjs.com/package/nextjs-http-supertest. It allows you to build an http server which will link endpoints with your nextJS handler.
I suggest you to use this pacakge: https://www.npmjs.com/package/nextjs-http-supertest. It allows you to build an http server which will link endpoints with your nextJS handler.
How is it better against ntarh? ntarh seems to be already established solution for Next.js endpoint unit-testing. It takes cares of all the boring unit-testing setup and doesn't use an HTTP server. It directly executes the endpoint function which seems to be more efficient and performant.
I suggest you to use this pacakge: https://www.npmjs.com/package/nextjs-http-supertest. It allows you to build an http server which will link endpoints with your nextJS handler.
How is it better against ntarh? ntarh seems to be already established solution for Next.js endpoint unit-testing. It takes cares of all the boring unit-testing setup and doesn't use an HTTP server. It directly executes the endpoint function which seems to be more efficient and performant.
As you said, ntarh is a solution for unit-testing. My package is a solution for integration-testing, this is not the same thing.
In unit testing you are only verifying that you're handler is working well, but you don't know if the correct handler is reach for a given endpoint. The aim of integration-testing, is to simulate the context of a browser or any other client performing an http request
Looking at your other repo, how would you go about testing an endpoint that uses middleware, or endpoints, in general, using
next-connect
?https://github.com/hoangvvo/nextjs-mongodb-app/blob/master/pages/api/users/%5BuserId%5D/index.js#L8
A potential test:
Doing something like this returns a 500. Maybe it's just me who is lacking testing knowledge. Any help would be appreciated.