Jasmine Unit Test, override only property in service

Viewed 115

this is my component spec file. It uses CalendarService. Inside CalendarService there are weekNames,monthNames,monthLongNames properties(which are just arrays of strings). Now... CalendarService has a lot of methods inside it. I want to be able to override only these 3 properties in my spec file but keep the rest of the methods and use them in the spec file. The reason why I want to override them is because they use another service to be created(e.g. weekNames = [this.translationService.formatMessage(), ... , ... , ...]). Which makes testing very difficult having a component with a service that has a service inside it.

EDIT: or another solution would be to override the translationservice with a mockservice. However translationservice is located inside CalendarService which uses my component. So i dont know how to do that.

describe('FCCalendarComponent', () => {
    let component: CalendarWrapperComponent;
    let fixture: ComponentFixture<CalendarWrapperComponent>;

    let calendarComponent: FCCalendarComponent;

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [
                FCCalendarComponent,
                CalendarWrapperComponent
            ],
            imports: [
                BrowserModule,
                FormsModule,
                ReactiveFormsModule,
                FCBaseModule,
                HttpClientModule,
                FCTranslateModule,
                FCCalendarModule
            ],
            providers: [
                FCTranslateLoader,
                CalendarService,
                FCTranslationService,
                {
                    provider: CalendarService, useValue: {
                        weekNames: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
                        monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
                        monthLongNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
                    }
                },
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(CalendarWrapperComponent);
        component = fixture.componentInstance;
        calendarComponent = fixture.debugElement.children[0].componentInstance;
        fixture.detectChanges();
    })


    it('should create component', () => {
        expect(component).toBeTruthy();
    });
});



@Component({
    selector: 'calendar-wrapper',
    template: `
        <fc-calendar value="2001.02.02" 
            minDate="2000.03.03" 
            maxDate="2002.04.04">
        </fc-calendar>
    `
})
export class CalendarWrapperComponent {

}
2 Answers

Either overriding three properties (as demonstrated by you) or mocking translation service is a legitimic solution.

Translation service is not "located" inside calendar services, but injected into it. So in order to mock it, you need to use provide+useValue mechanism, as you did for three properties (perhaps you would have to create translationMockService class and call useClass instead of useValue).

SOLUTION: If you have a service in your component and that service has another service used inside it. Instead of mocking the 'parent' service, you can mock the 'child' service. Simply by adding 'child' service to providers like so

FCTranslationService,
{
    provider: FCTranslationService, useValue: { }
},

and in beforEach overriding it with your mock service, like so

TestBed.overrideProvider(FCTranslationService, { useValue: new TranslateMockService() })

and in case you wanna know what mock looks like.

export class TranslateMockService {
    formatMessage() {
        return;
    }
}

The mock only has the method which is being used by the parent service and nothing else.

Related