jest failed because a promise is not in try catch

Viewed 29

I have two classes: Parent and Child. Parent class needs to initialize through a promise which I did during its construction:

// Parent.ts
class Parent {
  constructor() {
    this.init().then().catch();
  }

  private init(): Promise<boolean> {

  return new Promise((resolve, reject)=>{
    //do stuff.
    resolve(true);
    });
  }


  multiply(number): number {
    return number * USER_VALUES_PICK
  }
};

Now in child class I do:

class Child {
  private parent = new Parent();
  add(a: number, b:number): number {
    return parent.multiply(a + b);
  }
}

Now in my Child.test.ts:

it("add method", () => {
  const child = new Child();
  expect(child.add(1,1)).toStrictEqual(2 * USER_VALUES_PICK);
});

But the test fails stating a promise is not being caught:

node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read properties of undefined (reading 'map')".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

It passes if I don't call the init() method in Parent constructor method.

How do I go about testing this or what change should I make?

1 Answers

Your stack trace points to an unhandled rejection but for me it was a syntax error in your add method, you must use this to call a class property, anyway, you can use the reject method and handle the promise in your constructor as well, try the following:

Parent.ts

const USER_VALUES_PICK: number = 2;

// export the class
export default class Parent {
    constructor() {
      this.init()
        // handle the promises
        .then((data) => console.log(data))
        .catch((err) => console.log(err));
    }
  
    private init(): Promise<boolean> {
      return new Promise((resolve, reject) => {
        resolve(true);
        // add reject to promise
        reject(false);
      });
    }

    // type the input
    public multiply(number: number): number {
      return number * USER_VALUES_PICK;
    }
  }

Child.ts

// don't forget to import the parent class
import Parent from "./Parent";

export class Child {
  private parent = new Parent();

  public add(a: number, b: number): number {

    // use this to call the property
    return this.parent.multiply(a + b);
  }
}

Take a look at the working example in codesandbox.

Related