Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a service with multiple constructor parameters in NestJS

Background

When I'm testing a service that requires one parameter in the constructor, I have to initialize the service as a provider using an object rather than simply passing the service through as a provider:

auth.service.ts (example)

@Injectable()
export class AuthService {

  constructor(
    @InjectRepository(Admin)
    private readonly adminRepository: Repository<Admin>,
  ) { }

  // ...

}

auth.service.spec.ts (example)

describe('AuthService', () => {
  let authService: AuthService


  beforeEach(async () => {
    const module = await Test.createTestingModule({
        providers: [
          AuthService,
          {
            provide: getRepositoryToken(Admin),
            useValue: mockRepository,
          },
        ],
      }).compile()

    authService = module.get<AuthService>(AuthService)
  })

  // ...

})

See this issue on GitHub for the source of this explanation.


My issue

I have a service that requires 2 parameters in the constructor:

auth.service.ts

@Injectable()
export class AuthService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly authHelper: AuthHelper,
  ) {}

  // ...

}

How do I initialize this service in the test environment? I can't pass multiple values to useValue in the providers array. My AuthService constructor has 2 parameters and I need to pass them both in order for the test to work.

Here's my current (not working) setup:

auth.service.spec.ts

describe('AuthService', () => {
  let service: AuthService

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [AuthService],
    }).compile()

    service = module.get<AuthService>(AuthService)
  })

  it('should be defined', () => {
    expect(service).toBeDefined()
  })

  // ...

})

When I don't pass them in, I get the following error:

  ● AuthService › should be defined

    Nest can't resolve dependencies of the AuthService (?, AuthHelper). Please make sure that the argument at index [0] is available in the TestModule context.
like image 850
Jacob Avatar asked Jan 02 '23 05:01

Jacob


1 Answers

Simply create an entry in the providers array for each provider that is injected in your AuthService's constructor:

beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    providers: [
      AuthService,
      {provide: JwtService, useValue: jwtServiceMock},
      {provide: AuthHelper, useValue: authHelperMock},
    ],
  }).compile()

The test util Test.createTestingModule() creates a module just like your AppModule and hence also has a providers array that is used for dependency injection.

like image 163
Kim Kern Avatar answered Jan 13 '23 15:01

Kim Kern