nestjse2e-testing

How to mock Nest.js nested module


I'm working on e2e test for Nestjs app, one of the modules is using https://github.com/deligenius/aws-sdk-v3-nest module. I'm stuck with mocking it.

I can't figure out how to mock S3 client injected in attachment module. When running test, it actually use real S3 client.

Here what I have so far.

 // app.module
@Module({
  imports: [
    AttachmentsModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {
}

// attachment module
@Module({
  controllers: [],
  providers: [
    S3fileService,
  ],
  imports: [
    AwsSdkModule.registerAsync({
      clientType: S3Client,
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService<EnvConfigs, true>) => {
        const awsConfigs = configService.get('awsConfigs', { infer: true });
        return new S3Client({
          region: awsConfigs.region,
        });
      },
      inject: [ConfigService],
    }),
  ],
  exports: [S3fileService],
})
export class AttachmentsModule {}

// S3fileService service
@Injectable()
export class S3fileService {
  constructor( 
    @InjectAws(S3Client) private readonly s3: S3Client, // I want to mock this S3Client
  ) {
    console.log(s3);// during test this is real s3 instance
  }
}

// my test
import { S3Client } from '@aws-sdk/client-s3';
import { mockClient } from 'aws-sdk-client-mock';

const s3Mock = mockClient(S3Client);

describe('InvoicesController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
      providers: [/// this is not working
        {
          provide: S3Client,
          useValue: s3Mock,
        },
      ],
    })
      .overrideProvider(S3Client) // this is not working
      .useValue(s3Mock)
      .compile();

    app = moduleFixture.createNestApplication();

    await app.init();
  });
});


Solution

  • Turns out I need to use correct DI token. I have imported S3Client in service like @InjectAws(S3Client) private readonly s3: S3Client and under the hood it generating token something like AWS_SDK_V3_MODULE#S3Client#. o Im not sure this is correct way to do it , but it works!

    .overrideProvider('AWS_SDK_V3_MODULE#S3Client#') // this is working
    .useValue(s3Mock)