Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular mock service on component level

I have to mock service methods, which is injected on component level, not on module level. Here's how my component looks like:

@Component({
    selector: 'app-mycomponent',
    template: '<some html content>',
    ...
    providers: [MyService],
})
export class MyComponent implements OnInit {
    constructor(private myService: MyService) {}

    ngOnInit(): void {
        this.myService.myMethod();
    }
}

and my spec file:

define('MyComponent', () => {
    let component: MyComponent;
    let fixture: ComponentFixture<MyComponent>;
    let service: MyService;
    
    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            imports: [..some modules..],
            providers: [
                { provide: MyService, useClass: MyServiceStub }
            ],
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;
        service = TestBed.get(MyService);
        fixture.detectChanges();
    });

    it ('should call service method', () => {
        spyOn(service, 'myMethod');

        component.ngOnInit();

        expect(service.myMethod).toHaveBeenCalled();
    });
});

class MyServiceStub {
    myMethod(): void {}
}

When I run npm test, TC fails, complaining that expected method of service wasn't called. it would pass if I provided service on module level, but I need it to be in component level, any idea how to correctly configure spec to work with component level provided service?

like image 755
Arkadi Avatar asked Sep 20 '25 10:09

Arkadi


1 Answers

You can use TestBed.overrideComponent for that.

// Override component's own provider
TestBed.overrideComponent(
   MyComponent,
   {set: {providers: [{provide: MyService, useClass: MyServiceStub}]}}
)
.compileComponents();

See Angular documentation

like image 82
ChrisY Avatar answered Sep 23 '25 02:09

ChrisY