NewToAngular
NewToAngular

Reputation: 1115

Angular Unit Test - Mocked Service is not being used

Angular Unit Test - Mocked Service is not being used

I'm pretty new to coding and I am trying to write my own app to learn Angular. As a good developer I am writing tests for my code but I am having a little issue.

I have created a wrapper service that uses the Angular Material Dialog, this is the method in my component that calls the wrapper service (here's some code)

this how I declare the service in my component

constructor(private modalDialogWrapperService: ModalDialogWrapperService) {}

this is method that calls the service.

public assignInstrument(instrument: any): void {
    this.modalDialogWrapperService.openAssignmentWindow({
        product: 'instrument',
        type: instrument.type,
        serial: instrument.serial,
        id: instrument.id
    });
}

Now all this works fine but I want to test the component that when assignInstrument is executed the modalDialogWrapperService.openAssignmentWindow is called. Here is my test file

describe('InstrumentsPageComponent', () => {
    let component: InstrumentsPageComponent;
    let fixture: ComponentFixture<InstrumentsPageComponent>;
    let modalDialogWrapperServiceSpy: jasmine.SpyObj<ModalDialogWrapperService>;

    beforeEach(async(() => {
        const mockModalDialogWrapperService =
        jasmine.createSpyObj('ModalDialogWrapperService', ['openAssignmentWindow']);
        mockModalDialogWrapperService.openAssignmentWindow.and.returnValue(of({}));

        TestBed.configureTestingModule({
            imports: [MatTableModule, MatPaginatorModule, MatDialogModule, NoopAnimationsModule],
            declarations: [InstrumentsPageComponent, ChangeAssignmentComponent],
            providers: [{
                provide: ModalDialogWrapperService,
                useValue: mockModalDialogWrapperService}]
        })
        .overrideModule(BrowserDynamicTestingModule, { set: { entryComponents: [ChangeAssignmentComponent]}})
        .compileComponents();

    beforeEach(() => {
        fixture = TestBed.createComponent(InstrumentsPageComponent);
        modalDialogWrapperServiceSpy = TestBed.get(ModalDialogWrapperService);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    describe('assignInstrument', () => {
        it('should call the Modal Dialog Service', () => {
            component.assignInstrument({});
            expect(modalDialogWrapperServiceSpy.openAssignmentWindow).toHaveBeenCalledTimes(1);
        });
    });

Now this brings back the error "openAssignmentWindow to have been called once. It was called 0 times.". I've noticed that if I write console.log(this.modalDialogWrapperService); in my component's ngOnInit() it looks as if the dalDialogWrapperService does not get replaced in the Jasmine stub. What am I doing wrong?

Upvotes: 1

Views: 2742

Answers (1)

Fabian K&#252;ng
Fabian K&#252;ng

Reputation: 6183

Your approach might be a bit of an overkill if you just want to validate if the service method has been called. You could just set up a spy on the actual service instead of providing a mock service that does pretty much the same thing.

Here is how I would implement this test

In your first describe block add your a service reference:

let modalDialogWrapperService: ModalDialogWrapperService;

Provide it as you normally would in a module, but in your beforeEach(async()):

providers: [ModalDialogWrapperService]

In your beforeEach() get the service via the TestBed:

modalDialogWrapperService = TestBed.get(ModalDialogWrapperService);

And then your test would look like this:

describe('assignInstrument', () => {
  it('should call the Modal Dialog Service', () => {
    let spy = spyOn(modalDialogWrapperService, 'openAssignmentWindow').and.returnValue(of({}));
    expect(spy).not.toHaveBeenCalled();

    component.assignInstrument({});
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

This requires less code and looks a bit cleaner in my opinion.

Stackblitz can be found here.

Upvotes: 0

Related Questions