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"
}
Jest is a JavaScript testing framework designed to ensure correctness of any JavaScript codebase. It allows you to write tests with an approachable, familiar and feature-rich API that gives you results quickly. Jest is well-documented, requires little configuration and can be extended to match your requirements.
Our first friend is describe , a Jest method for containing one or more related tests. Every time you start writing a new suite of tests for a functionality wrap it in a describe block. As you can see it takes two arguments: a string for describing the test suite, and a callback function for wrapping the actual test.
Jest makes mocking easy by using a custom resolver for imports and enables you to use the mocked imports with mock function APIs to spy on function calls. The mock function comes in handy especially in unit testing as they let you test the function logic without having to worry about its dependencies.
Both Jest and Enzyme are meant to test the react applications. Jest can be used with any other Javascript framework, but Enzyme is meant to run on react only. Jest can be used without Enzyme, and snapshots can be created and tested perfectly fine. But the Enzyme adds additional functionality to it.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With