镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Comparing errors through deepEqual #3122

Description

@rpepato

I'm implementing tests for my js project and I need to compare an error returned from a rejected promise with an expected one.

It turns out that, no mater what is the content of the error object, assert.deepEqual always returns true as long as the two instances being compared are Errors.

The same behaviour does not occur when comparing strings, for example (node version 4.1.1):

node --version
v4.1.1

> let assert = require("assert");
undefined

> assert.deepEqual(new Error("a"), new Error("b"));
undefined

> assert.deepEqual(new String("a"), new String("b"));
AssertionError: [String: 'a'] deepEqual [String: 'b']
    at repl:1:8
    at REPLServer.defaultEval (repl.js:164:27)
    at bound (domain.js:250:14)
    at REPLServer.runBound [as eval] (domain.js:263:12)
    at REPLServer.<anonymous> (repl.js:393:12)
    at emitOne (events.js:82:20)
    at REPLServer.emit (events.js:169:7)
    at REPLServer.Interface._onLine (readline.js:210:10)
    at REPLServer.Interface._line (readline.js:549:8)
    at REPLServer.Interface._ttyWrite (readline.js:826:14)

Reading the documentation for the deepEqual assertion, I didn't found any mentions regarding something special when comparing Errors.

Is this behaviour intended by design? Am I missing something important or should a consider another strategy to deeply compare two Error objects (instances + messages)?

Activity

  1. added
    questionIssues asking questions about Node.js.
    assertIssues and PRs related to the assert subsystem.
    on Sep 30, 2015
  2. Trott commented on Sep 30, 2015

    @Trott
    Member

    This looks like it's caused by code in lib/assert.js that uses Object.keys() to get all the keys in the Error objects and then compares them. The Error objects have non-enumerable keys so Object.keys(new Error('a')); returns an empty array. So the errors are determined to be equal.

  3. Trott commented on Sep 30, 2015

    @Trott
    Member

    Possible fix: #3124

  4. Trott commented on Oct 19, 2015

    @Trott
    Member

    I'm afraid a fix for this is unlikely to land in Node.js. The API is now locked and users are encouraged to employ userland assertion libraries instead.

    If you don't want to use a userland assertion library for whatever reason, a workaround for your case might look like this:

    assert.deepEqual(error1.message, error2.message);
    assert.deepEqual(error1.name, error2.name);
    

    Or, more thoroughly (like, if you want the stack traces to match exactly, which you typically probably don't):

    var ka = Object.getOwnPropertyNames(error1).concat(Object.getOwnPropertySymbols(error1));
    var kb = Object.getOwnPropertyNames(error1).concat(Object.getOwnPropertySymbols(error2));
    
    ka.sort();
    kb.sort();
    
    assert.deepStrictEqual(ka, kb);
    
    for (var i = ka.length - 1; i >= 0; i--) {
      console.log(ka[i]);
      assert.deepEqual(error1[ka[i]], error2[ka[i]]); // use assert.deepStrictEqual() if that's what you want
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    assertIssues and PRs related to the assert subsystem.questionIssues asking questions about Node.js.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions