Giter VIP home page Giter VIP logo

testing-express-rest-api's Introduction

Testing Express REST API

Key takeaways

  • An understanding of how important testing is
  • Testing doesn't have to be complicated or difficult

What will you learn?

  • Testing a REST API end-to-end with Supertest & mongodb-memory-server
  • Mocking services
  • Testing from the controller to the service

Read: https://github.com/goldbergyoni/javascript-testing-best-practices

What you will need

What next?

  • Testing the API with Jest
  • Build a React.js user interface
  • Add Prometheus metrics to the API
  • Deploy the API with Caddy & Docker
  • Add Google OAuth

Data flow

Let's keep in touch

Buy me a Coffee

Sign up to DigitalOcean ๐Ÿ’–

testing-express-rest-api's People

Contributors

tomanagle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

testing-express-rest-api's Issues

Node 17: Could not connect to db error

Environment

  • node v17.0.1
  • npm 8.1.0
  • MongoDB 5.0.3 community edition installed from homebrew
  • macos catalina 10.15.7

Repro

git clone [email protected]:TomDoesTech/Testing-Express-REST-API.git
cd Testing-Express-REST-API
npm i
(make sure mongodb is ready)
npm run dev
(then this following error in the console after around 30s)

Error

> [email protected] dev
> ts-node-dev --respawn --transpile-only src/app.ts

[INFO] 02:35:24 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.4.3)
[2021-10-24T02:35:26+01:00] INFO: App is running at http://localhost:1337
[2021-10-24T02:35:56+01:00] ERROR: Could not connect to db

Workaround attempt

Removing async and await from the connect code appears to solve the problem at first glance.

diff --git a/src/app.ts b/src/app.ts
index 4a714e0..7b50c07 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -8,8 +8,8 @@ const port = config.get<number>("port");
 
 const app = createServer();
 
-app.listen(port, async () => {
+app.listen(port, () => {
   logger.info(`App is running at http://localhost:${port}`);
 
-  await connect();
+  connect();
 });
diff --git a/src/utils/connect.ts b/src/utils/connect.ts
index a6a4831..7d2b0c8 100644
--- a/src/utils/connect.ts
+++ b/src/utils/connect.ts
@@ -2,11 +2,11 @@ import mongoose from "mongoose";
 import config from "config";
 import logger from "./logger";
 
-async function connect() {
+function connect() {
   const dbUri = config.get<string>("dbUri");
 
   try {
-    await mongoose.connect(dbUri);
+    mongoose.connect(dbUri);
     logger.info("DB connected");
   } catch (error) {
     logger.error("Could not connect to db");

Once you make this change, you run into the same jwt malformed issue #1 followed by a new error (ERROR: MongooseError: Operation 'users.insertOne()' buffering timed out after 10000ms) after creating a user with Postman:

> [email protected] dev
> ts-node-dev --respawn --transpile-only src/app.ts

[INFO] 03:36:33 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.4.3)
[2021-10-24T03:36:34+01:00] INFO: App is running at http://localhost:1337
[2021-10-24T03:36:34+01:00] INFO: DB connected
JsonWebTokenError: jwt malformed
    at Object.module.exports [as verify] (/Users/phil/dev/Testing-Express-REST-API/node_modules/jsonwebtoken/verify.js:63:17)
    at verifyJwt (/Users/phil/dev/Testing-Express-REST-API/src/utils/jwt.utils.ts:16:25)
    at /Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:22:41
    at step (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:33:23)
    at Object.next (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:14:53)
    at /Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:4:12)
    at deserializeUser (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:9:21)
    at Layer.handle [as handle_request] (/Users/phil/dev/Testing-Express-REST-API/node_modules/express/lib/router/layer.js:95:5)
[2021-10-24T03:36:53+01:00] ERROR: MongooseError: Operation `users.insertOne()` buffering timed out after 10000ms
    Error: MongooseError: Operation `users.insertOne()` buffering timed out after 10000ms
        at /Users/phil/dev/Testing-Express-REST-API/src/service/user.service.ts:15:11
        at step (/Users/phil/dev/Testing-Express-REST-API/src/service/user.service.ts:33:23)
        at Object.throw (/Users/phil/dev/Testing-Express-REST-API/src/service/user.service.ts:14:53)
        at rejected (/Users/phil/dev/Testing-Express-REST-API/src/service/user.service.ts:6:65)
        at processTicksAndRejections (node:internal/process/task_queues:96:5)
MongooseServerSelectionError: connect ECONNREFUSED ::1:27017
    at NativeConnection.Connection.openUri (/Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/connection.js:796:32)
    at /Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/index.js:328:10
    at /Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5
    at new Promise (<anonymous>)
    at promiseOrCallback (/Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)
    at Mongoose._promiseOrCallback (/Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/index.js:1149:10)
    at Mongoose.connect (/Users/phil/dev/Testing-Express-REST-API/node_modules/mongoose/lib/index.js:327:20)
    at connect (/Users/phil/dev/Testing-Express-REST-API/src/utils/connect.ts:9:14)
    at Server.<anonymous> (/Users/phil/dev/Testing-Express-REST-API/src/app.ts:14:10)
    at Object.onceWrapper (node:events:509:28)
[ERROR] 03:37:04 MongooseServerSelectionError: connect ECONNREFUSED ::1:27017

JsonWebTokenError: jwt malformed

Encountered this error while investigating other issues I've been having around this codebase, I am reporting it here as someone had this problem in the other repository.

Environment

  • node v16.12.0
  • npm 8.1.0
  • MongoDB 5.0.3 community edition installed from homebrew
  • macos catalina 10.15.7

Repro

git clone [email protected]:TomDoesTech/Testing-Express-REST-API.git
cd Testing-Express-REST-API
npm i
(make sure mongodb is ready)
npm run dev
(send 'Create User' request in Postman)
(successful response in postman:)
{
    "email": "[email protected]",
    "name": "Jane Doe",
    "_id": "6174b21643dd23a0be37c83b",
    "createdAt": "2021-10-24T01:08:38.462Z",
    "updatedAt": "2021-10-24T01:08:38.462Z",
    "__v": 0
}

Then follows this error in the console:

Error

npm run dev

> [email protected] dev
> ts-node-dev --respawn --transpile-only src/app.ts

[INFO] 02:08:25 ts-node-dev ver. 1.1.8 (using ts-node ver. 9.1.1, typescript ver. 4.4.3)
[2021-10-24T02:08:27+01:00] INFO: App is running at http://localhost:1337
[2021-10-24T02:08:27+01:00] INFO: DB connected
JsonWebTokenError: jwt malformed
    at Object.module.exports [as verify] (/Users/phil/dev/Testing-Express-REST-API/node_modules/jsonwebtoken/verify.js:63:17)
    at verifyJwt (/Users/phil/dev/Testing-Express-REST-API/src/utils/jwt.utils.ts:16:25)
    at /Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:22:41
    at step (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:33:23)
    at Object.next (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:14:53)
    at /Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:4:12)
    at deserializeUser (/Users/phil/dev/Testing-Express-REST-API/src/middleware/deserializeUser.ts:9:21)
    at Layer.handle [as handle_request] (/Users/phil/dev/Testing-Express-REST-API/node_modules/express/lib/router/layer.js:95:5)

Pino's deprecated prettyPrint and its problem with Jest

I have the solution to this issue, I just wanted to share it.

I noticed when working on the previous chapter of this tutorial that pino complains saying that prettyPrint is deprecated for the logger().

(node:54078) [PINODEP008] PinoWarning: prettyPrint is deprecated, look at https://github.com/pinojs/pino-pretty for alternatives.

So, I found that the preferred method is using a transport option, like so:

Before

const log = logger({
  prettyPrint: true,
  base: {
    pid: false,
  },
  timestamp: () => `,"time":"${dayjs().format()}"`,
});

After

const log = logger({
  transport: {
    target: "pino-pretty",
    options: {
      colorize: true,
    },
  },
  base: {
    pid: false,
  },
  timestamp: () => `,"time":"${dayjs().format()}"`,
});

But starting on this tutorial for testing I found a head-scratching error faced me when using --detectOpenHandles:

Jest has detected the following 1 open handle potentially keeping Jest from exiting:

  โ—  WORKER

      4 | const testMode = process.env.NODE_ENV === "test";
      5 |
    > 6 | const log = logger({
        |                   ^

After a short amount of Googling I found that the transport option was to blame. To check, I restored prettyPrint: true, removed transport: {...} and the error disappeared.

I don't know if this is perhaps the best method to fix it, but noticing that the env variable NODE_ENV was set when running jest (which is then utilized by config to switch to a different config file, test.js) I decided to take advantage of it and wrote this adjustment:

// NODE_ENV is set to "test" when jest is running.
const inTest = process.env.NODE_ENV === "test";

const log = logger({
  enabled: !inTest,
  transport: !inTest ? {
    target: "pino-pretty",
    options: {
      colorize: true,
    },
  } : undefined,
  base: {
    pid: false,
  },
  timestamp: () => `,"time":"${dayjs().format()}"`,
});

That solved it and I hope this is helpful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.