Sinon: Confusing "fake.yields" in document

Created on 27 May 2019  路  4Comments  路  Source: sinonjs/sinon

Describe the bug
In "fakes" document at https://sinonjs.org/releases/v7.3.2/fakes/, there's a section about 'yields':

image

I find this very confusing. The signature says 'callback' should be the first argument, and a required one, followed by optional values. However, in the example, only values are provided, not callback. Then the sentence "fake expects the last argument to be a callback and will invoke it with the given arguments" is also confusing. I understand that "fake" in the example is a function, and in the example the only argument, also the last argument, is a callback (console.log) . However "given arguments" is very confusing. From the example, apparently the "given arguments" of "sinon.fake.yields" is used to invoke the callback, not the arguments given to "fake". And I don't know if "fake" requires the last argument to be a callback, what other arguments are used for......

So I'm totally lost here and cannot figure out how fake.yields should be used in test...... is it just me or the document is indeed confusing?

To Reproduce

https://sinonjs.org/releases/v7.3.2/fakes/

Expected behavior

Better explanation of fake.yields

Screenshots

Context (please complete the following information):

  • Library version:
  • Environment:
  • Example URL:
  • Other libraries you are using:

Additional context

Easy Documentation Help wanted

Most helpful comment

It's useful with callback invoking APIs, like all the node APIs. Here is an example:

sinon.replace(fs, 'readFile', sinon.fake.yields(null, 'file content'));

All 4 comments

You are right: it's super confusing and I don't understand it as it is, either. It also seems wrong, the callback is presented as the first argument, while the text says it's the last.

When I get lost, I usually just grep the tests for the term (here: yields) ...
https://github.com/sinonjs/sinon/blob/master/test/stub-test.js#L1511

This is me testing this out:

> spy = sinon.spy()
[Function: proxy]
> fake = sinon.fake.yields(1,2,3)
[Function: proxy]
> fake(console.log)
1 2 3
undefined
> sinon.fake.yields(1,2,3,spy)
[Function: proxy]
> spy.called
false
> sinon.fake.yields(spy,1,2,3)
[Function: proxy]
> spy.called
false
> fake(spy)
undefined
> spy.called
true

From this little test run it seems as if the docs are wrong. It doesn't use a callback at all, as far as I see, if passed into yield - only the resulting fake. This is inline with how it works with normal stubs (which fake are based upon, so no wonder). So if you had clicked the link to the tests it's basically this:

  1. You set up what you want your fake to invoke a passed in callback with: fake = sinon.fake.yields(arg1,arg2).
  2. You invoke the fake with a callback: fake( myCallback ).

That callback will now have been invoked with arg1 and arg2. Feel free to push a PR that fixes the docs!

Then I don't understand the reason behind 'yields'. Why don't just invoke callback(arg1, arg2...) but first instantiate a fake, and call fake(callback) instead of callback(arg1, arg2...)? What's the use case?

It's useful with callback invoking APIs, like all the node APIs. Here is an example:

sinon.replace(fs, 'readFile', sinon.fake.yields(null, 'file content'));

Thanks, now I understand the usage and will make a pull request to fix the document. I will also have a look at yieldsSync.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fearphage picture fearphage  路  4Comments

OscarF picture OscarF  路  4Comments

brettz9 picture brettz9  路  3Comments

optimatex picture optimatex  路  4Comments

tinganho picture tinganho  路  3Comments