My task involves writing unit tests for an angular 5 application. To achieve this, I utilize jasmine + jest
(as jest is preferred over karma in my organization due to its test speed).
For testing the behavior of my component (refer to the code below), I create a test that subscribes to the same Observable
as the component being tested. I then wait for 2 seconds, hoping that the component's subscription code has had enough time to execute, and finally check for any internal changes in the component.
However, the issue arises as the number of tests increases, resulting in longer completion times for the tests. I believe there must be a more efficient way to test this type of code.
- How should I approach this situation? I have explored using
async
but struggled to adapt it to my requirements. - How can I ensure that my tests run after the component's subscription block completes?
- Is there a method to avoid the 2-second waiting period and instead wait for the component's subscription block to finish?
Your assistance on this matter would be highly appreciated.
- Component:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { SomeService } from './some.service';
@Component({
selector: 'app-dummy',
templateUrl: './dummy.component.html',
styleUrls: ['./dummy.component.scss']
})
export class DummyComponent implements OnInit, OnDestroy {
isEditable: Boolean;
//...
private aSubscriber;
constructor(private someService: SomeService) {
this.aSubscriber = someService.anObservable$.subscribe(value => {
this.isEditable = value;
});
}
ngOnInit() { }
ngOnDestroy() {
this.aSubscriber.unsubscribe();
}
}
- Service:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class SomeService {
private aSubject = new Subject<any>();
anObservable$ = this.aSubject.asObservable();
constructor() { }
notify(value) {
this.aSubject.next(value);
}
}
- Spec file:
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { DummyComponent } from './dummy.component';
import { SomeService } from './some.service';
describe('DummyComponent', () => {
let component: DummyComponent;
let fixture: ComponentFixture<DummyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DummyComponent],
providers: [SomeService]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DummyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should subscribe to anObservable and set values according to the received one',
inject([SomeService], (service: SomeService) => {
service.anObservable$.subscribe(value => {
setTimeout(() => { }, 2000);
//Test that values are correctly set in the component under test.
expect(component.isEditable).toBeTruthy();
//...
});
service.notify(true);
}));
});