Reputation: 321
I am currently making an API with typescript, node, express and testing with jest and supertest. I had no problem when I was using Javascript, but I recently changed my project file from JS to TS including test files, and when I start testing, I get the error below in all my test suites on supertest request part and this is one of my test suites on my terminal when I start test.
TypeError: app.address is not a function
37 | it("should return 400 if email is invalid", async () => {
38 | const res = await request(server)
> 39 | .post("/api/users/auth/register")
| ^
40 | .send({
41 | email: "nomail",
42 | password: "validpassword123",
This is my test files auth.test.ts:
import * as request from 'supertest';
import { User } from '../../../../src/models/User';
import * as mongoose from 'mongoose';
import getKeys from '../../../../src/config/keys';
describe("/api/users/auth", () => {
let server;
let accessToken = "Bearer accessToken";
let email;
let password;
beforeAll(async () => {
server = import('../../../../src/index')
await mongoose.connect(getKeys().mongoURI);
})
afterAll(async () => {
await server.close();
await mongoose.disconnect();
})
it("should return 400 if email is invalid", async () => {
const res = await request(server)
.post("/api/users/auth/register")
.send({
email: "nomail",
password: "validpassword123",
name: "name"
});
expect(res.status).toBe(400);
expect(res.body).toHaveProperty('errArray')
});
}
and This is my src/index.ts file, which is Entry point.
import * as express from 'express';
import * as passport from 'passport';
import * as bodyParser from 'body-parser';
import * as path from 'path';
import * as session from 'express-session';
import getKeys from './config/keys';
const port = 3001 || process.env.PORT;
const server = app.listen(port, () =>
console.log(`Server running on port ${port}`)
);
export default server;
I've tried changing export and importing server syntax to all commonjs syntax and install and set all dependencies relevant to this including @types/supertest, @types/jest, ts-jest , here is my settings jest.config.js
module.exports = {
verbose: true,
testURL: 'http://localhost',
testEnvironment: "node",
roots: [
"<rootDir>"
],
transform: {
"^.+\\.tsx?$": "ts-jest"
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
globals: {
"ts-jest": {
"tsConfigFile": "tsconfig.json"
}
},
moduleFileExtensions: [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
}
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist",
"moduleResolution": "node",
"sourceMap": true,
"module": "commonjs",
"allowJs": true,
"target": "es5",
"noUnusedParameters": false,
"allowUnreachableCode": true,
"allowUnusedLabels": true,
"types": [
"jest",
"node",
"express",
"mongoose",
"body-parser",
"supertest"
],
"lib": [
"es2015"
]
},
"include": [
"./src/**/*",
"index.ts"
],
"exclude": [
"./node_modules",
"**/*.spec.ts",
"**/*.test.ts"
]
}
package.json
"scripts": {
"test": "jest --watchAll --runInBand",
"coverage": "jest --coverage",
"start": "ts-node src/index.ts",
"server": "./node_modules/nodemon/bin/nodemon.js",
"client": "npm start --prefix ../client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
"devDependencies": {
"@types/body-parser": "^1.17.0",
"@types/express": "^4.16.0",
"@types/jest": "^23.3.12",
"@types/mongoose": "^5.3.7",
"@types/node": "^10.12.18",
"@types/supertest": "^2.0.7",
"jest": "^23.6.0",
"nodemon": "^1.18.9",
"supertest": "^3.3.0",
"ts-jest": "^23.10.5",
"ts-node": "^7.0.1",
"typescript": "^3.2.2"
}
Upvotes: 10
Views: 7123
Reputation: 102547
The reason is your server
passed into supertest
is undefined
. supertest
will use app.address()
internally, see this line. That's why it throw an error:
TypeError: app.address is not a function
If you want to import the server
dynamically, You should change:
let server;
beforeAll(async () => {
server = import('../../../../src/index')
})
to:
let server;
beforeAll(async () => {
const mod = await import('../../../../src/index');
server = (mod as any).default;
});
E.g.
index.ts
:
import express from 'express';
const app = express();
app.post('/api/users/auth/register', (req, res) => {
res.status(400).json({ errArray: [] });
});
const port = 3001 || process.env.PORT;
const server = app.listen(port, () => console.log(`Server running on port ${port}`));
export default server;
index.test.ts
:
import request from 'supertest';
describe('/api/users/auth', () => {
let server;
beforeAll(async () => {
const mod = await import('./');
server = (mod as any).default;
});
afterAll((done) => {
if (server) {
server.close(done);
}
});
it('should return 400 if email is invalid', async () => {
const res = await request(server)
.post('/api/users/auth/register')
.send({
email: 'nomail',
password: 'validpassword123',
name: 'name',
});
expect(res.status).toBe(400);
expect(res.body).toHaveProperty('errArray');
});
});
Integration test result with coverage report:
☁ jest-codelab [master] ⚡ npx jest --coverage --verbose /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/54230886/index.test.ts
PASS src/stackoverflow/54230886/index.test.ts (10.306s)
/api/users/auth
✓ should return 400 if email is invalid (56ms)
console.log src/stackoverflow/54230886/index.ts:437
Server running on port 3001
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 50 | 100 | 100 | |
index.ts | 100 | 50 | 100 | 100 | 9 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 11.875s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/54230886
Upvotes: 2