ts-mockito
ts-mockito copied to clipboard
When with literal object argument not working
Whenever i call "when" with primitive type argument it gets work without any problems and the function return the desired value inside the test.
But when calling "when" with argument of reference type variables like literal object or a Map the function doesn't get mocked and it doesn't return the desired value from when.
// it works fine and the function resolves true inside my test
when(browserNode.getStateChannel('some string')).thenResolve(true);
// it doesn't work and the function doesn't resolve true inside my test
when(browserNode.getStateChannel({ channelAddress: 'some channel address'})).thenResolve(true);
is there any way to get "when" mocking works with literal objects arguments like above!
TLDR: You can use deepEqual or objectContaining i.e.
when(something.method(deepEqual({ ... })).thenResolve(true)
Without knowing the internals of ts-mockito this is likely due to the fact that object equality is checked by reference in JS. Being able to make sure a method is called with or returns an exact instance of an object is useful. For example (perhaps a bit contrived) consider an implementation of the identity function. You'd most likely not want the following implementation to pass.
const identity = x => ({...x})
Otherwise you'd end up with weird behavior like
const obj = { prop: 5 }
identity(obj) === obj // returns false
The following test would fail with this implementation of identity
const obj = { prop: 5 }
expect(identity(obj)).to.equal(obj) // fails
That being said in most situations like the one you mention, you probably don't care whether the object passed as argument matches exactly by reference. The actual behavior we want in most cases is probably closer to deepEqual or objectContaining but these matchers may also lead to unexpected behavior. Let's say you have some procedural style code and your client is supposed to call a method modifyAndReturnTrueOnSucess that modifies the object given as argument and you test looks like this
...
when(mock.modifyAndReturnTrueOnSucess(deepEqual(obj)).thenReturn(true))
...
but your client looks like this (it calls modifyAndReturnTrueOnSucess with a copy of the object)
...
thing.modifyAndReturnTrueOnSucess(copy(obj))
...
// at this point the code may assume obj was modified even though it was not - a copy of the object was
Your test may still pass even though modifyAndReturnTrueOnSucess was not called with the exact instance of the object that was supposed to be modified. This is because deepEqual essentially matches the argument by value.
Thanks @EmilEriksen! Would be great to have deepEqual in the README docs! 🙂
Looks like a PR has already been created #94. @NagRock could we get this merged in please?
Thanks guys, Can you merge the PR please so i can close this one as well