mjackson / expect

Write better assertions
MIT License
2.29k stars 117 forks source link

Spy not working when depdendent service is destructured #169

Closed batjko closed 8 years ago

batjko commented 8 years ago

Hi there,

Following the issue noted in #106, I found out why my spy won't work, despite following the documentation properly:

Scenario: You're testing a module and its function called MyModule.getStuff(), which itself depends on another service that you therefore want to stub, say using expect.spyOn(otherService, 'getData');.

Issue: The spy will not be called if MyModule's getStuff() is imported using ES6 destructuring, e.g.:

/* MyModule.js */

// will be caught by the spy:
const otherService = require('./otherService');

// won't be caught by the spy:
const { getData } = require('./otherService');

That's what stumped me on the issue for a good day. Changing the import back to the oldschool version made my test with the spy work just fine.

ljharb commented 8 years ago

It's impossible to spy on named imports. You can only spy on object properties, and a named import is a direct binding to the thing being exported.

That said, destructuring works just fine, unless the module has cached a reference to the function directly. In other words, if the module is intentionally being robust against someone mutating the object, it's also intentionally preventing anyone from spying on that thing.

batjko commented 8 years ago

I'm rather new to this, so forgive my ignorance regarding the workings of spies. But why can a spy not be directly attached to a the destructured function?

ljharb commented 8 years ago

@batjko because the mechanism by which all kinds of spies in JS functions is by replacing an object property with a spy function. There's nothing in JS that allows replacing a direct reference to a value with another one when it's not in scope (via reassignment)

batjko commented 8 years ago

That explains a few things. Thanks!

didaquis commented 4 years ago

Maybe this can help: https://stackoverflow.com/questions/60149391/how-to-use-jasmine-js-spy-on-a-required-function