nestjs-i18n
nestjs-i18n copied to clipboard
I18n context not found in e2e test for microservice
I'm getting once again the error that the I18n context couldn't be found (#435).
ERROR [I18nService] I18n context not found! Is this function triggered by a processor or cronjob? Please use the I18nService
The microservice works nicely. But I now want to implement some e2e tests, and when executing the test, the error is thrown and the test fails.
The app successfully initializes, but as soon as I call client.send()
, the error is thrown.
@Controller()
export class AppController {
@MessagePattern({ type: 'pdf', context: 'project' })
async generatePdf(@Payload() data, @I18n() i18n: I18nContext) {
i18n.translate('key');
// some implementation
return 'some-string';
}
}
describe('AppController (e2e)', () => {
let app: INestApplication;
let client: ClientProxy;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
AppModule,
ClientsModule.register([
{ name: 'ExportService', transport: Transport.TCP }
])],
})
.overrideProvider(I18N_LOADER_OPTIONS)
.useValue({ path: join(__dirname, '../../../../libs/i18n/src/lib/translations/')})
.compile();
app = moduleFixture.createNestApplication();
app.connectMicroservice({
transport: Transport.TCP
});
await app.startAllMicroservices();
await app.init();
client = app.get<ClientProxy>('ExportService');
await client.connect();
});
it('should return base64-encoded file', async () => {
const response = await lastValueFrom(client.send({ type: 'pdf', context: 'project' }, { someData: true, lang: 'de' }))
expect(typeof response === 'string').toBeTruthy();
});
afterAll(async () => {
await app.close();
client.close()
});
});
I'm using version [email protected]
.
@Brakebein so it only gives this error while running tests and not in normal conditions?
Yes, exactly.
As a workaround, I managed to mock the creation of the I18nContext. As long as I don't test that the actual translations are correct according to the language key, this works so far and the test doesn't fail.
const i18nService = app.get(I18nService);
jest.spyOn(I18nContext, 'current').mockImplementation(() => new I18nContext('de', i18nService));
I am wrapping the i18n module in my own module that has it's own t
function that is already typed (so I don't need to import types in multiple places.
I am running into the same issue: when I use my module in a controller it translates nicely, but if I create a testing module from my AppModule and try to use the app .get
to inject my service, the context's current
function returns undefined
.
@Brakebein @matzeso apologies if I've missed something in the documentation, but, can you post an example (top-to-bottom) of using the i18nService
in a context other than http request or test? For example, say I have a @Cron
task that simply outputs notifications on a regular schedule in x-language?
How does one successfully instantiate the i18n
service for common use in basically any "service.ts" context? I imagine something like: I18nContext.current().i18n.t...
but that somehow also seems wrong. 🤔
Sorry, I don't have any use case for @Cron
together with i18n. But shouldn't it be possible to just instantiate the I18nContext (as it works in my mocked implementation above)?
@Injectable()
export class TasksService {
private readonly logger = new Logger(TasksService.name);
constructor(@Inject(I18nService) private readonly i18nService: I18nService) {}
@Cron('45 * * * * *')
async handleCron() {
const i18n = new I18nContext('en', this.i18nService);
this.logger.debug(await i18n.t('key'));
}
}
@Brakebein if you are manually specifying language, you dont need the context. You can do
return this.i18n.t('test.HELLO',{ lang: 'en' });