Pablo Melo
Pablo Melo

Reputation: 123

How to spyOn a method called in the constructor?

I have a ionic project with a method in the constructor of a component that is called depending of a condition. I 'm using Jasmine and I want to spyOn that method to check if it is called.

This is the constructor of the component:

export class MyComponent {
    public test: boolean;

    constructor(public service: MyService) {
        if(test) {
            service.getX();
        }
    }
}

In my spec.ts I have to instantiate the component in order to spyOn the method but isn't work since the method has already been called in the constructor.

beforeEach(() => {

    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;

});

it('Test case #1', () => {
    component.test = true;

    spyOn(component.service, 'getX'); //The method has already been called in the constructor called in beforEach above

    expect(component.service.getX).toHaveBeenCalled();
})

How can I spyOn a method called in the constructor?

Upvotes: 11

Views: 14429

Answers (3)

Huantao
Huantao

Reputation: 935

to mock a service in component's constructor, you need provide the mock before TestBed.createComponent

for example

beforeEach(() => {
  mockService = TestBed.get(Service); 
  spyOn(mockService, 'getSomeValue').and.returnValue({value});
  fixture = TestBed.createComponent(MyComponent);
  component  = fixture.componentInstance;
})

Upvotes: 9

Plastikaweb
Plastikaweb

Reputation: 31

Running on the same problem, I've just achieved to test a method called within the constructor, firing the expectation within a setTimeout:

 it('should call methodName on instance', () => {
   spyOn(instance, 'methodName').and.callThrough();   
   setTimeout(() => {
     expect(instance.methodName).toHaveBeenCalled();
   });
 });

Upvotes: 1

user4676340
user4676340

Reputation:

Thank to prototype inheritance, you do it like this :

spyOn(MyService.prototype, 'getX');
const mock = new MyComponent({getX: () => null});
expect(MyService.prototype.getX).toHaveBeenCalled();

You can also do it like this, which is clearer to read :

const serviceMock = new MyService();
spyOn(serviceMock, 'getX');
const mock = new MyComponent(serviceMock);
expect(serviceMock.getX).toHaveBeenCalled();

Be sure to create a mock of your component to trigger the constructor, because if you don't, it will only be done with the TestBed (and your spy won't be in place).

Upvotes: 4

Related Questions