2

I'm trying to use co-mocha to test some nested generators functionality in my koa app. The class works just fine at runtime, but when I attempt to test the functionality, I cannot get the nested generator to run in my test.

Class being tested:

import Promise from 'bluebird'

class FooService {
  _doAsync(){
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({
          foo: 'FOO'
        })
      }, 500)
    })
  }

  create(){
    console.log('This never gets logged')
    let self = this
    return function*(){
      console.log(`This doesn't either`)
      return yield self._doAsync()
    }
  }
}
export default new FooService()

Test File

import fooService '../services/foo-service'
import Chai from 'chai'
let expect = Chai.expect

describe('Testing generators', () => {
  it('Should just work', function *(){
    console.log('This log never happens')
    let result = yield fooService.create()
    expect(result).to.equal({foo: 'FOO'})
  })
})

I'm running mocha w/ --require co-mocha and Node 4.2.6

While the tests complete w/o errors, NONE of the console above ever get logged and so I'm quite sure the actual test generator is never running at all.

If I try using the npm package, mocha-generators instead, while I get the log from inside the test generator, the underlying generator returned from the create() method on the service never fires...

What am I doing wrong??

RavenHursT
  • 2,336
  • 1
  • 25
  • 46
  • 1
    You probably want to `yield* fooService.create()()` – Bergi Feb 08 '16 at 23:34
  • Never export class instances! Either export the class, or don't use `class` syntax and create an object literal instead. – Bergi Feb 08 '16 at 23:35
  • @Bergi how would changing that line change anything (in the case of `co-mocha`) when the generator that line is sitting in, never appears to run in the first place? – RavenHursT Feb 08 '16 at 23:42
  • @Bergi Your line modification worked with the `mocha-generators` library! Thank you! Please add it as an answer? On a side note, why the assertion that we should "never" export a class instance? I was under the impression that, in the case of singletons, this pattern works quite well due to `require`'s build-in caching? – RavenHursT Feb 08 '16 at 23:49
  • 1
    @RavenHursT The primary issue is that if you are exporting a class singleton, you might as well just export an object. You gain nothing by using class syntax. You could just as easily `export default function create(){}` or if you do have multiple functions, `export function create(){}`. – loganfsmyth Feb 09 '16 at 00:09
  • @RavenHursT: And worse, not only do you gain nothing, but you also create a useless prototype chain and leak the class constructor of the would-be singleton. See also [here](http://stackoverflow.com/q/10406552/1048572). – Bergi Feb 09 '16 at 09:01

1 Answers1

2

Without mocha-generators, the it callback returns a generator that will not be run by anyone. You'd need to wrap it in co manually so that mocha would receive a promise.

With mocha-generators, your generator is executed but yields a generator function. That's not expected, you are supposed to yield promises. You need to call the generator function that the create() call returns yourself, and then you shouldn't yield a generator itself but rather delegate to it via yield*:

let result = yield* fooService.create()();
Bergi
  • 630,263
  • 148
  • 957
  • 1,375