Sinon: calledWith ignores symbols used as property keys

Created on 3 Feb 2019  路  5Comments  路  Source: sinonjs/sinon

Describe the bug
Asserting calledWith ignores mismatched properties if they keys are JavaScript symbols.

To Reproduce
Steps to reproduce the behavior:

var sinon = require('sinon');
var mock = sinon.mock();

mock({
    [Symbol("a")]: true
});

sinon.assert.calledWith(
    mock,
    {
        [Symbol("a")]: false
    }
);

Expected behavior
The above script should throw an AssertError because the mock was called with an object containing a true value when we were expecting a false value. It should behave similarly to this example that uses non-symbolic keys:

var sinon = require('sinon');
var mock = sinon.mock();

mock({
    a: true
});

sinon.assert.calledWith(
    mock,
    {
        a: false
    }
);

image

Context (please complete the following information):

  • Library version: 7.2.3
  • Environment: Node.js v10.8.0
  • Other libraries you are using: None; I reproduced this issue in a newly initialized npm project.

Additional context
I started working on a solution, but I wanted to raise an issue before opening pull requests like the contributing guide suggests to make sure I'm going down the right path. Using this change for samsam and this change for formatio, I get the behavior I expected for the script in the _To Reproduce_ section:

image

Because symbols are unique, this:

var sinon = require('sinon');
var mock = sinon.mock();

mock({
    [Symbol("a")]: true
});

sinon.assert.calledWith(
    mock,
    {
        [Symbol("a")]: true
    }
);

will throw an AssertError (thanks @pettyalex for pointing this out):

image

This, however, will not throw an AssertError:

var sinon = require('sinon');
var mock = sinon.mock();

const symbol = Symbol("a");

mock({
    [symbol]: true
});

sinon.assert.calledWith(
    mock,
    {
        [symbol]: true
    }
);

Unfortunately, the samsam change breaks one unit test:

image

This is because arguments has a property symbol called iterator:

> function test() { return Object.getOwnPropertySymbols(arguments) } test();
[ Symbol(Symbol.iterator) ]

Most helpful comment

I like your suggestion. I'll put that solution together and open a PR for both samsam and formatio.

All 5 comments

Thank you for putting this detailed analysis and code changes together. We're definitely lacking proper Symbol support in Sinon and should do something about it.

Regarding your suggested solution, I think the fix should be slightly different: I'd say we should check the expectation for any symbol properties and only compare those to the actual. This means that additional symbol properties being added to the actual object do not break existing assertions. If we want to enforce strict matching of all symbols, then this would be a breaking change, because Sinon never looked at symbol properties before.

Any opinions or other ideas @sinonjs/sinon-core?

I like your suggestion. I'll put that solution together and open a PR for both samsam and formatio.

That's some very detailed analysis, thank you 鉂わ笍

I like the proposed solution that doesn't break existing assertions 馃憤

@mantoni @mroderick samsam and formatio pull requests for your consideration. Although I implemented the proposed solution and all existing unit tests pass, I still have concerns about the backwards compatibility of the samsam change, which I detail in the solution section.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NathanHazout picture NathanHazout  路  3Comments

fearphage picture fearphage  路  3Comments

byohay picture byohay  路  3Comments

stephanwlee picture stephanwlee  路  3Comments

fearphage picture fearphage  路  4Comments