jestjsnestjsnestjs-testing

Nest.js testing module, can not override provider injected into another provider, undefined received


I have Nest.js app, where certain provider is injected into another provider:

    export class AppService {
      public constructor(private readonly appInnerService: AppInnerService) {}
    }

AppService has a method publish which calls appInnerService send method. I created unit tests for AppService, where I want to mock AppInnerService provider:

      describe('App service', () => {
          let appService: AppService;
          const appInnerService = {
            send: jest.fn(),
          };
        
          beforeAll(async () => {
            const moduleRef = await Test.createTestingModule({
              providers: [AppService, AppInnerService],
            })
              .overrideProvider(AppInnerService)
              .useValue(appInnerService)
              .compile();
        
            appService = moduleRef.get<AppService>(AppService);
          });
    
          it('should work', () => {
            appService.publish({});
    
            expect(appInnerService.send).toHaveBeenCalled();
          });
        }

Above code doesn't work, AppInnerService isn't injected into AppService, instead undefined is passed to constructor. Why above test isn't working and how can I fix it (without manually creating AppService class with mocked service, I want to use testing module created by @nestjs/testing package)?


Solution

  • For closure on the problem: AppService needed to be decorated with @Injectable() to get typescript to reflect the constructor parameter metadata. With just Injectable() as was there, it's just a function call and not a decorator, so the metadata was not reflected and Nest could not act upon it.