Nest: Dependency injection inside Unit testing

Created on 1 Oct 2017  ·  5Comments  ·  Source: nestjs/nest

Hi,

I have two components that need to talk to each other, to avoid the circular dependency issue, I'm using this.moduleRef.get on both components to access the instance methods.

When doing unit test with @nestjs/testing after creating the module and declare both components, the DI doesn't works:

Scenario 1:

  • Component1 - declares dependency on Component2 via moduleRef
  • Component2 - declares dependency on Component1 via moduleRef
  • server behaviour: works
  • unit test behaviour: fails (both c1 -> c2 & c2 -> c1)

Scenario 2:

  • Component1 - declares dependency on Component2 via moduleRef
  • Component2 - declares dependency on Component1 via constructor
  • server behavour: works
  • unit test behaviour: fails for c1 -> c2 & works for c2 -> c1

So I can't get it working :(

Thanks!

question 🙌

Most helpful comment

It's because the testing module is not calling application lifecycle hooks (onModuleInit and onModuleDestroy). You can just call the method manually slightly_smiling_face

Hi, @kamilmysliwiec. Is there any plan to make the testing module call application lifecycle hooks? It would be nice to have that too.
PS: Nest is awesome :+1:

All 5 comments

Writing a simple example illustrating the issue (4.0.2 version):

app.module.ts:

import { Module } from '@nestjs/common';
import { A } from './a';
import { B } from './b';

@Module({
  components: [ A, B ]
})
export class ApplicationModule { }

a.ts:

import { Component, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { B } from './b';

@Component()
export class A implements OnModuleInit {
  private b: B;

  constructor(
    private readonly moduleRef: ModuleRef
  ) { }

  onModuleInit() {
    this.b = this.moduleRef.get<B>(B);
    this.callB();
  }

  whoIam() {
    console.log('I am A');
  }

  callB() {
    this.b.whoIam();
  }
}

b.ts

import { Component, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { A } from './a';

@Component()
export class B implements OnModuleInit {
  private a: A;

  constructor(
    private readonly moduleRef: ModuleRef
  ) { }

  onModuleInit() {
    this.a = this.moduleRef.get<A>(A);
    this.callA();
  }

  whoIam() {
    console.log('I am B');
  }

  callA() {
    this.a.whoIam();
  }
}

a.spec.ts:

import { Test } from '@nestjs/testing';
import { ApplicationModule } from './app.module';
import { A } from './a';
import { B } from './b';

describe('Dependencies tests', () => {
  let a: A;
  let b: B;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      // modules: [ ApplicationModule ],
      components: [ A, B ]
    }).compile();
    a = module.get<A>(A);
    b = module.get<B>(B);
  });

  it('should work', async () => {
    expect(a.callB()).toBe('I am B');
    expect(b.callA()).toBe('I am A');
  });
});

Starting the application with normal NestFactory.create(ApplicationModule) works as expected:

[Nest] 92610   - 2017-10-1 16:09:33   [InstanceLoader] ApplicationModule dependencies initialized
I am B
I am A

but when running the test with jest:

 FAIL  src/a.spec.ts
  ● Dependencies tests › should work

    TypeError: Cannot read property 'whoIam' of undefined

      at A.callB (src/a.ts:23:11)

Thanks

Hi @jgordor,
It's because the testing module is not calling application lifecycle hooks (onModuleInit and onModuleDestroy). You can just call the method manually :slightly_smiling_face:

Thanks! calling it manually worked :)

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      components: [ A, B ]
    }).compile();
    a = module.get<A>(A);
    a.onModuleInit();
    b = module.get<B>(B);
    b.onModuleInit();
  });

It's because the testing module is not calling application lifecycle hooks (onModuleInit and onModuleDestroy). You can just call the method manually slightly_smiling_face

Hi, @kamilmysliwiec. Is there any plan to make the testing module call application lifecycle hooks? It would be nice to have that too.
PS: Nest is awesome :+1:

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings