Angular unit test if component method is called according to a data from a service

南笙酒味 提交于 2019-12-23 22:36:37

问题


I can't figure out how to test if a component method is fired or not on service data condition...

service looks like:

@Injectable()
export class SomeService {

    someData() {
        return true;
    }
}

comp:

export class SomeComponent {

    constructor(private someService: SomeService) { 

        if (this.someService.someData()) {
            this.someMethod();
        } else {
            console.log('keep kalm!');
        }
    }

    someMethod() {
        console.log('some method is fired!')
    }
}

test:

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

    let mockSomeService = {
        someData: () => true
    }

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [SomeComponent],
            providers: [
                {
                    provide: SomeService, useValue: mockSomeService
                }
            ]
        })
        .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SomeComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    it('method should be called', () => {
        spyOn(component, 'someMethod'); 

        expect(component.someMethod).toHaveBeenCalled(); 
    });
});

The component someMethod fires but test fails with:

Expected spy someMethod to have been called.

How can I fix this?

Thanks in advance!


回答1:


you are setting up the spy too late. By the time you mount the spy on service, it has already been constructed and someMethod has been called. So after defining the component call the spy

it('method should be called', () => {
        var spy = spyOn(component, "someMethod").and.callThrough();
        expect(component).toBeDefined();
        expect(spy);
        expect(component.someMethod).toHaveBeenCalled(); 
 });



回答2:


You have to create the spy before you create the component, because spies can't look in the past and since your method is only called in constructor, it hasn't been called after you created the spy.

You should move your initialization to either ngOnInit method or a simple init() method called in constructor, this way to can call the init method or ngOnInit and check that someMethodhas been called.




回答3:


Oke It is fixed! thanks to the answer from @Supamiu

Incase someone will need it in the future:

Move the initialization into ngOnInit, remove fixture.detectChanges(); from beforeEach and execute it in the test. So:

Comp:

constructor(private someService: SomeService) { }

ngOnInit() {
    if (this.someService.someData()) {
        this.someMethod();
    } else {
        console.log('keep kalm!');
    }
}

test:

beforeEach(() => {
    fixture = TestBed.createComponent(SomeComponent);
    component = fixture.componentInstance;
    // fixture.detectChanges(); <<< Remove this
});

it('method should be called', () => {
    spyOn(component, 'someMethod'); 
    fixture.detectChanges(); // trigger ngOnInit here

    expect(component.someMethod).toHaveBeenCalled(); 
});


来源:https://stackoverflow.com/questions/48024481/angular-unit-test-if-component-method-is-called-according-to-a-data-from-a-servi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!