Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using jest with node assert got wrong error type. #7547

Open
poppinlp opened this issue Dec 25, 2018 · 19 comments
Open

Using jest with node assert got wrong error type. #7547

poppinlp opened this issue Dec 25, 2018 · 19 comments
Assignees
Labels

Comments

@poppinlp
Copy link

poppinlp commented Dec 25, 2018

🐛 Bug Report

The assert module in nodejs will throw error when assertion fail. It will throw a AssertionError If the second parameter is a string. But if the second parameter is an instance of Error, it will throw it instead of AssertionError.

I've tried this code and got the expected error.

const assert = require('assert');
const err = new Error('error message');

assert.ok(false, err);

But in my test case, i got an AssertionError.

To Reproduce

You may run this test case, it will fail:

const assert = require('assert');
const err = new Error('error message');

test('assert error object', () => {
  expect(() => {
    assert.ok(false, err);
  }).toThrow(err);
});

The failed error message is:

image

Expected behavior

Pass the test case. I know i could use something like .toThrow(err.message) to pass it, but i want to check the error type also.

Link to repl or repo (highly encouraged)

Just run the case above. :)

Run npx envinfo --preset jest

Paste the results here:

  System:
    OS: macOS 10.14.1
    CPU: (8) x64 Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz
  Binaries:
    Node: 11.5.0 - ~/.nvm/versions/node/v11.5.0/bin/node
    npm: 6.4.1 - ~/.nvm/versions/node/v11.5.0/bin/npm
  npmPackages:
    jest: ^23.6.0 => 23.6.0
@SimenB
Copy link
Member

SimenB commented Dec 25, 2018

This is weird. Running the snippet above behaves differently in node and through jest.

I added try-catch just to make sure jest doesn't catch the error and format it.

const assert = require('assert');
const err = new Error('error message');

try {
  assert.ok(false, err);
} catch (e) {
  console.log(e.stack);
}

Jest:

    AssertionError [ERR_ASSERTION]: Error: error message
        at Object.ok (/Users/simen/Development/jest/weird.test.js:5:10)
        at Runtime._execModule (/Users/simen/Development/jest/packages/jest-runtime/build/index.js:709:13)
        at Runtime.requireModule (/Users/simen/Development/jest/packages/jest-runtime/build/index.js:354:14)
        at /Users/simen/Development/jest/packages/jest-jasmine2/build/index.js:199:13
        at Generator.next (<anonymous>)
        at asyncGeneratorStep (/Users/simen/Development/jest/packages/jest-jasmine2/build/index.js:27:24)
        at _next (/Users/simen/Development/jest/packages/jest-jasmine2/build/index.js:47:9)
        at /Users/simen/Development/jest/packages/jest-jasmine2/build/index.js:52:7
        at new Promise (<anonymous>)
        at /Users/simen/Development/jest/packages/jest-jasmine2/build/index.js:44:12

Node:

Error: error message
    at Object.<anonymous> (/Users/simen/Development/jest/weird.test.js:2:13)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
    at startup (internal/bootstrap/node.js:285:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)

@thymikee @rickhanlonii any ideas?

@thymikee
Copy link
Collaborator

IIRC we re-throw Node assert errors with custom AssertionError: https://github.com/facebook/jest/blob/master/packages/jest-circus/src/formatNodeAssertErrors.js

@SimenB
Copy link
Member

SimenB commented Dec 25, 2018

Yeah, but that shouldn't happen when I catch it locally, unless we inject a fake assert module?

@pedrottimark pedrottimark self-assigned this Dec 26, 2018
@pedrottimark
Copy link
Contributor

This is a use case for us to consider when deciding on a solution for #4724

For more info about the error class see: https://nodejs.org/dist/latest-v10.x/docs/api/assert.html#assert_class_assert_assertionerror

@nicolas-van
Copy link

I confirm this behavior.

This is a burden in one of our use cases as we use assert for tasks unrelated to unit testing. Jest having unexpected side effect on the assert lib wherever it is used makes it unreliable as a unit testing framework in our case.

@adamdama
Copy link

I find it quite worrying that when I am running the code in the test environment it is being handled differently than it would in production. I should be able to rely on the fact my code will run the same in both environments otherwise the tests can't really be trusted.

@Lehks
Copy link

Lehks commented Apr 1, 2021

Are there any news on this issue? I just ran into the same problem and I'd hate to write my own assert function just to work around a longstanding bug in Jest.

@criskurtin
Copy link

Same thing here, I'm using the node's assert function to do some assertions unrelated to unit testing and this behaviour causes the custom Error class to be substituted with the AssertionError. Because of this, all custom fields get lost.

@nicolas-van
Copy link

Does anybody have a workaround for this problem ? (One that does not involve using a different assertion library in the base code)

@abiusx
Copy link

abiusx commented Oct 13, 2021

It took me 30 minutes of googling just to find this thread. Why would the library override default assert and don't even mention it anywhere in the docs?

@Westermann
Copy link

👍 Also keen on a solution here.

@ArloysMacias
Copy link

@sagi-arbroknot
Copy link

Any news on that?
It has been quite a while.

@truemoroz
Copy link

same issue

@Carl-Foster
Copy link

This is a fairly significant issue with our codebase as we use assert to handle much of our data integrity checks. The errors that are provided with the second argument also encode much of our errors messaging within the server. With Jest or Expect seemingly re-throwing the error as an AssertionError, we no longer can properly test the what is valid and quite helpful code.

@windward-hive
Copy link

thanks jest. having to do this multiple times is very convenient 👍
image_2023-08-29_161106386

@Alexsey
Copy link

Alexsey commented Aug 29, 2023

@maybesmurf if you are really doing this all over the project, you should consider creating your own custom matcher that will do this unwrapping for you

@tqhoughton
Copy link

posting in case anyone else stumbles on this, adding this mock to my test files fixes the issue but to other people's points it would be nice if this followed the NodeJS spec more closely.

// normally we would not need to mock nodejs internals but in this case Jest globals are incorrect
// relevant github issue: https://github.com/jestjs/jest/issues/7547
jest.mock('assert', () => ({
  __esModule: true,
  default: (statement: unknown, err: Error) => {
    if (!statement) {
      throw err
    }
  }
}))

@tqhoughton
Copy link

Checking in on this thread I ended up completely abandoning trying to mock assert "correctly" since many other libraries use assert under the hood and depending on which order you are mocking things and importing libraries you can easily end up in a state where a third party library calls your own custom assert mock and breaks things due to it not being 100% correct.

This is an unfortunate case where the easiest solution is to use a third party module instead of node built-ins due to how Jest decides to override node defaults.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests