1

I'm using NestJS with Jest and getting Matcher error: expected value must be a function error when run following unit test. I have set invalid email in mockBody. Did I missed anything here?

app.service.ts

@Injectable()
export class UserService {
  constructor(private emailService: EmailService) {}

  async registerUserInquiry(user: UserDto): Promise<{ email: string }> {
    try {
      await sendEmail(user);
    } catch (error) {
      throw new HttpException('Something went wrong!', HttpStatus.BAD_REQUEST);
    }
    return {
      email: user.email,
    };
  }
}

app.service.spec.ts

describe("registerUser()", () => {
  it("Should throw bad request error when passing invalid data", async () => {
    const mockBody: UserDto = {
      name: "John Doe",
      message: "Example inquiry message",
      email: "@example",
      mobile: "+60121234567",
    };

    expect(async () => await service.registerUserInquiry(mockBody)).toThrow(
      new HttpException("Something went wrong!", HttpStatus.BAD_REQUEST)
    );
  });
});

email.config.ts

export const sendEmail = async (user: User) => {
  const transporter = nodemailer.createTransport({
    ... // service & auth
  });

  const options = {
   ... // email info
  };

  await transporter.sendMail(options, function (error, info) {
    try {
      console.info(error);
      return info;
    } catch (error) {
      console.error(error);
      throw error;
    }
  });
};

Error: enter image description here

Johnny
  • 261
  • 7
  • 22
  • 2
    `expect(response).toThrowError();` makes no sense because: 1. you need to pass a function to defer execution so the error can be caught (see https://jestjs.io/docs/expect#tothrowerror); but also 2. if it did error you'd never reach that line - it's a promise, `await`ing it means the error ends up in the `catch` block. I'd strongly recommend looking at the options in https://jestjs.io/docs/tutorial-async. – jonrsharpe Apr 04 '22 at 16:05
  • `expect(() => {service.register(mockBody);}).toThrow(new HttpException('Something went wrong!', HttpStatus.BAD_REQUEST));` can u please provide some example ? – Johnny Apr 04 '22 at 16:20
  • That _doesn't_ throw an error, it returns a promise that rejects. – jonrsharpe Apr 04 '22 at 16:21
  • Actually because you included the braces it returns undefined, and ignores the promise that rejects, causing an unhandled promise error. – jonrsharpe Apr 04 '22 at 16:27
  • `expect(received).toThrow(expected) Expected message: "Something went wrong!" Received function did not throw` im getting this error now. `expect(async () => await service.registerUserInquiry(mockBody)).toThrow(new HttpException('Something went wrong!', HttpStatus.BAD_REQUEST);` – Johnny Apr 04 '22 at 16:34
  • Please [edit] the question to give a [mre]. – jonrsharpe Apr 04 '22 at 16:39
  • (But again, async function return promises. They don't throw errors.) – jonrsharpe Apr 04 '22 at 16:44
  • 1. That's not a MRE, 2. you haven't updated the error, and 3. https://stackoverflow.com/questions/71740269/jest-matcher-error-expected-value-must-be-a-function#comment126783069_71740269. Read the linked docs, which explain several methods for testing promises. – jonrsharpe Apr 04 '22 at 16:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/243608/discussion-between-johnny-and-jonrsharpe). – Johnny Apr 05 '22 at 06:37

1 Answers1

2

Instead of this

expect(async () => await service.registerUserInquiry(mockBody)).toThrow(
  new HttpException("Something went wrong!", HttpStatus.BAD_REQUEST)
);

Try this one

await expect(service.registerUserInquiry(mockBody)).rejects.toThrowError(...)

Your function is a promise which means it is not throwing an error but instead it rejects.

Aurelia Peters
  • 2,169
  • 1
  • 20
  • 34
n1md7
  • 2,854
  • 1
  • 12
  • 27
  • `expect(received).rejects.toThrowError() Received promise resolved instead of rejected Resolved to value: {"email": "@example"}` received this error now – Johnny Apr 05 '22 at 06:28
  • 1
    @Johnny then you presumably haven't set up the test such they it _does_ reject, without a MRE it's hard to say, but the test failure is now about the behaviour of your code not that the assertion itself is wrong. – jonrsharpe Apr 05 '22 at 06:59