1

Context

My issue is that my ngOnInit function calls many sub functions asynchronously by using Firestore to populate a form from one document as well as subscribing to various collections to display lists of data. This gets very tedious to test as I then have to ensure things are subscribing properly and values are being returned in the correct order.

According to the Angular docs:

However, it's often more productive to explore the inner logic of application classes with isolated unit tests that don't depend upon Angular. Such tests are often smaller and easier to read, write, and maintain.

Which in my opinion would make preventing the ngOnInit (through a spy) a valid way of

  1. Isolating tests and

  2. Reducing complexity when initializing the tests

You can then explicitly call each function separately and only test what is needed, instead of having ngOnInit calling the functions (and possible you as well).

This is exactly how I have gone about it so far:

Component

ngOnInit() {
    console.log('init');
    this.setup();
}

setup() {
    this.firebaseService.setup(_ => {
        this.checkNewOrEdit();
    });
}

...

Spec

...

beforeEach(() => {
    fixture = TestBed.createComponent(Component);
    component = fixture.componentInstance;
    spyOn(component, 'ngOnInit');
    fixture.detectChanges();
});
    
it('should be created', () => {
    fixture.whenStable().then(_ => {
        expect(component).toBeTruthy();
    });
});
    
   
it('should call checkNewOrEdit() on setup()',
    () => {
        spyOn(component, 'checkNewOrEdit');
        callbackValue = 'success';
        component.setup();
        expect(component.checkNewOrEdit).toHaveBeenCalled();
    }
);

Which is working fine for me so far.

Is this an acceptable solution? Or are there better ways of going about this?

Community
  • 1
  • 1
Matthew Mullin
  • 7,116
  • 4
  • 21
  • 35
  • 1
    What I would do is put in **mock respond** and then call **ngOnInit**. This way you can check which function is tiggered. Your implementation seems fine. – Swoox Oct 23 '17 at 10:20

1 Answers1

0

I had problems further down the line in terms of variables not being set previously.

This solution does work but it just adds further complexity further down the line. I would recommend solving the problem initially, then you don't have to worry about how and where variables where set later

I solved my problems by editing my firebase mocks to include all the collections and docs I subscribe to throughout the initialisation chain. I think I must have forgotten a a doc or collection somewhere.

Matthew Mullin
  • 7,116
  • 4
  • 21
  • 35