How to test toThrow exception?

410 views Asked by At

In my stencil component I am using @Watch to perform validation as below

  @Watch('name')
  validateName(newValue: string) {
    const isBlank = typeof newValue !== 'string' || newValue === '';
    console.log('AYE!', isBlank);
    if (isBlank) { throw new Error('name: required') };
  }

Now I would like to test this in jest

it('throws error when name is not supplied', async () => {
    const { root } = await newSpecPage({ components: [MyComponent], html: '<my-component></my-component>' });

    expect(() => {
      root.name = '';
    }).toThrow(new Error('name: required'))  
  })

And the result I'm getting is as below

expect(received).toThrow(expected)

Expected message: "name: required"

Received function did not throw

  47 |     expect(() => {
  48 |       root.name = '';
> 49 |     }).toThrow(new Error('name: required'))  
     |        ^
  50 |   })
  51 | });
  52 | 

console.log
  AYE! true

  at MyComponent.validateName (src/xxx/my-component.tsx:31:13)
      at Array.map (<anonymous>)

I'm wondering how should I catch the error threw from validateName?

2

There are 2 answers

1
Simon Hänisch On BEST ANSWER

After changing a prop, you'll have to use the async waitForChanges(). You can check whether it throws by calling it and then using rejects.toEqual(...). Also you'll have to return the expect(...) statement, otherwise your test will pass before the async code has finished (and you'd get a UnhandledPromiseRejectionWarning in your console).

it('throws error when name is not supplied', async () => {
  const { root, waitForChanges } = await newSpecPage({
    components: [MyComponent],
    html: '<my-component></my-component>'
  });

  root.name = '';

  return expect(waitForChanges()).rejects.toEqual(new Error('name: required'));
})
0
Isaac On

Instead of using toThrow, we can achieve the similar result via try catch block as below.

Also Stencil providdes waitForChanges method which allow us to alter the value of properties and wait for it to take effect

it('throws error when name is not supplied', async () => {
    try {
      const { root, waitForChanges } = await newSpecPage({ components: [MyComponent], html: `<my-component name="xxx"></my-component>` });
      root.name = '';
      await waitForChanges()
    } catch (e) {
      expect(e).toStrictEqual(Error('name: required'));
    }
  })