igor Smirnov
igor Smirnov

Reputation: 321

How to resolve dependency of nestjs-i18n `I18nService` in testing? Cannot create proxy with a non-object as target or handler

I want to test service (lets call it HiService) that depends on I18nService. HiService has many branches and return different message from each branch. I want to make sure, that test hit the right branch, so I want to check that right message is returned.

For this I need real I18nService, not his mock.

But when I add I18nService to providers and I18nModule to imports I get an error "Cannot create proxy with a non-object as target or handler"

What should I do with such tokens as 'I18nLanguagesSubject', 'I18nOptions', 'I18nTranslationsSubject', etc? And why I18nService not getting his option from I18nModule.forRoot? Why 'I18nService' themself end up in createMock(token) if I specified him in providers?

describe('HiService', () => {
    let service: HiService;

    beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            providers: [
                HiService,
                I18nService,
            ],
            imports: [
                I18nModule.forRoot({
                    fallbackLanguage: Language.en,
                    loaderOptions: {
                        path: path.join(__dirname, '../../../i18n/'),
                        watch: true,
                    },
                    typesOutputPath: path.join(__dirname, '../../src/generated/i18n.generated.ts'),
                    resolvers: [new HeaderResolver(['x-user-language'])],

                }),
            ]
        })
            .useMocker((token) => {
                switch (token) {
                }
                return createMock(token);
            })
            .compile();
    
        service = module.get<BalanceService>(HiService);
    });

    it('test', async () => {
            const hello = service.hi('en');
            expect(hello).toBe("hello");
            const hola = service.hi('es');
            expect(hola).toBe("hola");
     }

Upvotes: 0

Views: 351

Answers (1)

igor Smirnov
igor Smirnov

Reputation: 321

Got it.

  1. Don't need I18nModule.forRoot in tests at all.
  2. For some reason instead of providers: [I18nService] should use
.useMocker((token) => {
    switch (token) {
        case 'I18nService':
            return I18nService;
    }
    return createMock(token);
})

Don't know why, but this fixed test. So the final code became

describe('HiService', () => {
    let service: HiService;

    beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            providers: [
                HiService,
                I18nService,
            ],
        })
            .useMocker((token) => {
                switch (token) {
                    case `I18nService`:
                        return I18nService;
                }
                return createMock(token);
            })
            .compile();
    
        service = module.get<BalanceService>(HiService);
    });

    it('test', async () => {
            const hello = service.hi('en');
            expect(hello).toBe("hello");
            const hola = service.hi('es');
            expect(hola).toBe("hola");
     }

Upvotes: 1

Related Questions