question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[new rule] prefer-to-throw / consistent-expect-error

See original GitHub issue

I would like to see a new rule named prefer-to-throw, or consistent-expect-error that would (preferably) default to the .toThrow syntax.

If consistent-expect-error is set to use the try/catch syntax, an error should be thrown if expect.hasAssertions (or a variation of) has not been set.

const throwSyncError = () => {
    throw new Error('sync example');
};

const throwAsyncError = async () => {
    throw new Error('async example');
};

describe('prefer-to-throw - sync', () => {
    test('eslint pass', () => {
        expect(() => throwSyncError()).toThrow('async example');
    });

    test('eslint error', () => {
        expect.hasAssertions();
        try {
            throwSyncError();
        } catch (error) {
            expect(error.message).toEqual('sync example');
        }
    });
});

describe('prefer-to-throw - async', () => {
    test('eslint pass', async () => {
        await expect(throwAsyncError()).rejects.toThrow('async example');
    });

    test('eslint error', async () => {
        expect.hasAssertions();
        try {
            await throwAsyncError();
        } catch (error) {
            expect(error.message).toEqual('async example');
        }
    });
});

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
G-Rathcommented, Jun 18, 2020

Can you elaborate about the difference between your suggested solution to one without invoking the async function inside the expect?

re my response: I had just woken up and have not retained the context for this issue since it’s 6 months old, so I freeballed it to push you in the right direction 😂

I expected it to be “mostly right”, but should have mentioned “something like [code example]” to make that clearer.

@SimenB’s code example is actually also “almost” - it actually needs to be:

const promiseMeSomething = () => new Promise((rs, rj) => rj('hello world'));

test('it works', async () => {
  await expect(promiseMeSomething()).rejects.toThrow('hello world');
});

So to break down whats going on here, and why:

  • rejects is required because toThrow is sync, and promises don’t “throw” in the try/catch sense
  • rejects requires a promise, which is why we call promiseMeSomething directly instead of in a function
    • This is where @SimenB was “almost” - his example would have been rejected with Matcher error: received value must be a promise.
    • This also answers your question I believe about the difference between the two code lines you provided
  • Finally, we need await because otherwise the test will “pass” with a promise rejection error that jest won’t see.

Overall I think at this point (thats again without having the context from 6 months ago), I would personally recommend using a utility function of some kind if you want to test things on the actual error:

const getError = async (call: Function): Error => {
  try {
    await call();

    throw new Error('no error was thrown!');
  } catch(error) {
    return error;
  }
}

The benefit to me is that the getError utility function is a clear easy to recognize pattern that solely “inverts” errors & returns by returning any errors that are thrown, and throwing if no errors are.

That way you don’t duplicate that across your tests, where it’s possible make a typo that could still pass in your testbase. Granted we have tools to help reduce the likelihood of this, but it’s still possible.

(This is one of the reasons why no-try-expect was introduced).

In addition, we’re balancing usefulness & time-saving-potential against complexity and maintainability:

I think that the warning should be removed if hasAssertions exists or offer a better text.

Detecting if hasAssertions exists isn’t just a one-line function call - it requires parsing the whole function body and then some; that’s not including things other ways you can add expect.hasAssertions, such as as a hook for every test.

However, improving the text is definitely something we could do easily; I’ve not looked into the message myself, but more than happy to discuss that 😃

2reactions
SimenBcommented, Feb 8, 2020

almost - need to be await expect(() => store.dispatch(actions.someFailingAction)).rejects.toThrow();.

We don’t have a really clean way if you wanna make multiple assertions on the error, though.

Read more comments on GitHub >

github_iconTop Results From Across the Web

prefer-ts-expect-error - TypeScript ESLint
This rule reports any usage of @ts-ignore , including a fixer to replace with @ts-expect-error . ❌ Incorrect; ✓ Correct. // @ts-ignore
Read more >
Rules - ESLint - Pluggable JavaScript Linter
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
Read more >
How to test the type of a thrown exception in Jest
My current testing framework is AVA and I can test it as a second argument t.throws method, like here: it('should throw Error with...
Read more >
eslint-plugin-jest - npm
ESLint rules for Jest. Latest version: 27.1.7, last published: 11 days ago. Start using eslint-plugin-jest in your project by running `npm i ...
Read more >
Linter rules - Dart
Details about the Dart linter and its style rules you can choose. ... Error rules. These rules identify possible errors and other mistakes...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found