Mocking TranslationService in Angular

44 Views Asked by At

I'm new in using Karma and unit tests in Angular and I'm struggling... I have a method I want to test when the service I'm using is returning a bad request

The method is

this._commandService.commandsGet(this.oem, this.countryCode).pipe(takeUntil(this._unsubscribeAll)).subscribe(
            response => {
                this.commands = Object.values(response.data);
                this.commandDropDownList(this.commands);
            },
            () => {
                const errorMessage = true;
                const errorMessageContent =
                    this._translateService.instant('CONTENT.There was a problem with the Command Service') +
                    '. ' +
                    this._translateService.instant('CONTENT.Please contact your administrator');
                this._messageService.errorMessage(errorMessage, errorMessageContent);
            }
        );

The problem I'm having is when I try to check that the translation service is being called with the correct parameters.

I'm using the TranslateTestingModule from 'ngx-translate-testing', and I can see the service is being called and doing what's expecting.

But when I try to spy on it, I'm getting an error saying that the service has not been called. I have noticed when I'm debugging, that the code flow is passing twice instead of one, first time, the mocked values are as expected, and the second they are 'undefined' I think the issue is probably there, why is it coming twice in the error block?

Here is my test code:

Initial setup:


    TestBed.configureTestingModule({
        imports: [
            HttpClientModule,
            TranslateModule.forRoot({
                loader: {
                    provide: TranslateLoader,
                    useClass: TranslateFakeLoader
                }
            }),
            MatDialogModule,
            HttpClientTestingModule,
            TranslateTestingModule.withTranslations('en', en)
        ],
        declarations: [DialogSendcommandComponent, TranslatePipe],
        providers: [
            CommandService,
            MessageService,
            { provide: MatDialogRef, useValue: mockMatDialog }
        ]
    }).compileComponents();
}));

afterEach(() => {
    TestBed.resetTestingModule();
});

Test with the issue:


describe('Test Methods _commandService.commandsGet', () => {

        beforeEach(() => {
            TestBed.overrideProvider(MAT_DIALOG_DATA, { useValue: dataAml });
            translateService = TestBed.inject(TranslateService);
            commandService = TestBed.inject(CommandService);
            httpMock = TestBed.inject(HttpTestingController);
            fixture = TestBed.createComponent(DialogSendcommandComponent);
            component = setComponent(formBuilder, component, fixture);

        });

        afterEach(() => {
            httpMock.verify();
        })

        it('should display error message if commandsGet returns error', (done: DoneFn) => {

            spyOn(commandService, 'commandsGet').and.returnValue(throwError({ status: 400, error: 'Bad Request' }));
            const instantSpy = spyOn(translateService, 'instant').and.returnValues(
                'Translated Text 1',
                'Translated Text 2'
            );

            commandService.commandsGet(dataAml.oem, dataAml.countryCode).subscribe({
                next: () => {
                    // This should not be called for a bad request
                    fail('Expected error response');
                },
                error: (error) => {
                    // Expecting an error response
                    expect(error.status).toBe(400);
                    expect(error.error).toBe('Bad Request');
                    expect(instantSpy).toHaveBeenCalledTimes(2);
                    expect(instantSpy.calls.allArgs()).toEqual([
                        ['CONTENT.There was a problem with the Command Service'],
                        ['CONTENT.Please contact your administrator'] 
                    ]);
                }
            });
            component.ngOnInit();
            fixture.detectChanges();
            done();
        });

    });

Thanks for your help

1

There are 1 best solutions below

0
Christèle Legeard On

So I fixed the problem removing that piece of code:

commandService.commandsGet(dataAml.oem, dataAml.countryCode).subscribe({
                next: () => {
                    // This should not be called for a bad request
                    fail('Expected error response');
                },
                error: (error) => {
                    // Expecting an error response
                    expect(error.status).toBe(400);
                    expect(error.error).toBe('Bad Request');
                    expect(instantSpy).toHaveBeenCalledTimes(2);
                    expect(instantSpy.calls.allArgs()).toEqual([
                        ['CONTENT.There was a problem with the Command Service'],
                        ['CONTENT.Please contact your administrator'] 
                    ]);
                }
            });
    ```

and calling the ngOnInit method, like this:

it('should display error message if commandsGet returns error', (done: DoneFn) => {

        const translatedText1 = 'There was a problem with the Command Service';
        const translatedText2 = 'Please contact your administrator';

        spyOn(commandService, 'commandsGet').and.returnValue(throwError({ status: 400, error: 'Bad Request' }));
        const instantSpy = spyOn(translateService, 'instant').and.returnValues(en.CONTENT[translatedText1], en.CONTENT[translatedText2]);
        
        component.ngOnInit();

        expect(instantSpy).toHaveBeenCalledTimes(2);
        expect(instantSpy.calls.allArgs()).toEqual([
            [`CONTENT.${translatedText1}`],
            [`CONTENT.${translatedText2}`]
        ]);

        done();
    });