typedi icon indicating copy to clipboard operation
typedi copied to clipboard

feature: Disable `eager` service loading for tests

Open South-Paw opened this issue 4 years ago • 3 comments

Description

I started using the eager flag on some of my @Services that I would expect to be started as soon as they are registered (Database, Logger, Mailer, etc) which works great 👍

However when unit testing, these services are registering themselves during tests that don't require them and then beginning their start up routines (initializing connections etc) which causes tests to fail or have other issues

Proposed solution

Would it be possible to set some configuration on the Container to instruct it to ignore eager services when testing?

Other alternatives I've tried/thought about

  • Mocking the eager services in a setupTests file (however this didn't seem to work, they are still registered then starting up)
  • I suppose I could remove the this.start() calls from the service's constructors, but then I'll have to get them from the container to manually call start() on them (which sort of defeats the purpose of the eager 😄)

Thanks

South-Paw avatar Jun 28 '21 11:06 South-Paw

Sort of related to the conversation in #126

If its relevant, the services I'm starting using eager look very similar to the following...

@Service({ eager: true })
export class EngineImpl {
  private readonly engine;

  constructor() {
    // this may be a database connection or a mailer transport in the real-world
    this.engine = createEngine();

    this.start();
  }

  private async start() {
    console.log("start your engines...");

    try {
      if (await this.engine.start()) {
        console.log("engine goes brrrrrr");
      }
    } catch (err) {
      console.log("oops the engine stalled, retrying in 3 seconds...");

      setTimeout(() => this.start(), 3000);
    }
  }
}

South-Paw avatar Jun 28 '21 11:06 South-Paw

However when unit testing, these services are registering themselves during tests that don't require them and then beginning their start up routines (initializing connections etc) which causes tests to fail or have other issues

How do you export these services? Unit tests should import it tests only. So your eager services should not be imported at all if you are not specifically testing them.

NoNameProvided avatar Jan 13 '22 12:01 NoNameProvided

(yikes, sorry about the spam: I had an issue with Git and had to force push it a few times, didn't realise linking the issue would notify on every commit...)

Mocking the eager services in a setupTests file (however this didn't seem to work, they are still registered then starting up)

The way I did this in my TypeDI fork was turning off eager initialisation by default, and having it enable-able by a flag. That way, you can easily enable it in your application code prior to importing any eager services, but by default it's disabled -- this makes it much easier to test.

It's enabled by a enableEagerLoading flag which tells the container to eagerly run any eager services it encounters. However, you may want to implement a buffer of eager services: if the flag wasn't enabled when the eager service was registered, it'll be added to a buffer and, if enableEagerLoading is then called, that buffer will be flushed and each service within would be passed to get.

https://github.com/freshgum-bubbles/typedi/blob/c3d4f88328ac1b18962515c6ce90db300a3f273b/src/container-instance.class.ts#L957-L959

freshgum-bubbles avatar Jun 25 '23 17:06 freshgum-bubbles