问题
I have a class in angular8 application with following ngOnit method
ngOnInit(): void {
this.setCustomizedValues();
this.sub = PubSub.subscribe('highlightEntity', (subId, entityIdentifier: string) => {
document.querySelector(entityIdentifier).classList.add('highlight');
setTimeout(() => {
document.querySelector(entityIdentifier).classList.remove('highlight');
}, 2000);
});
}
I have initialised the following test case
describe('aComponent', () => {
let httpCallerServiceStub = jasmine.createSpyObj('httpCallerServiceStub', ['get']);
let fixture: ComponentFixture<aComponent>;
let componentInstance: aComponent;
localStorage.clear();
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [aComponent],
providers: [
{
provide: HttpCallerService,
useValue: httpCallerServiceStub
}],
imports: [CommonModule, CmcSpinnerModule, NgbModule],
}).compileComponents();
fixture = TestBed.createComponent(aComponent);
componentInstance = fixture.componentRef.instance;
fixture.autoDetectChanges();
});
describe('ngOnInit method', () => {
beforeEach(() => {
fixture.componentInstance.customized = {};
});
it('should initialize with minimum input', () => {
// Triggers ngOnInit
fixture.detectChanges();
expect(fixture.componentInstance.customized).toEqual({});
});
});
So when I run this it randomly throwing the following error
"message": "An error was thrown in afterAll\nTypeError: Cannot read property 'classList' of null\n at <Jasmine>\n at webpack:///components/aComponent/aComponent.ts:33:53
Here is console error in karma test runner,
and here is what the file suggest
So after this point however number of test I write ahead, the issue still remains the same, sometime it works, sometime it doesnt.
Can you please tell me what to do with pubsub.subscriber and timeout inside ngonit?
回答1:
Since you're messing with the DOM
, ngOnInit
can be too early for that. The DOM
has not yet been painted. Try moving the logic to ngAfterViewInit
ngAfterViewInit() {
this.sub = PubSub.subscribe('highlightEntity', (subId, entityIdentifier: string) => {
document.querySelector(entityIdentifier).classList.add('highlight');
setTimeout(() => {
document.querySelector(entityIdentifier).classList.remove('highlight');
}, 2000);
});
}
And to test the setTimeout
, you can use fakeAsync
and tick
.
import { fakeAsync, tick } from '@angular/core/testing';
...
it('should initialize with minimum input', fakeAsync(() => {
// Triggers ngOnInit
fixture.detectChanges();
// do your assertions for ngAfterViewInit
// make 2s pass in a fake way
tick(2000);
// do your assertions for the setTimeout callback
expect(fixture.componentInstance.customized).toEqual({});
}));
来源:https://stackoverflow.com/questions/64242278/how-to-write-test-cases-for-subscriber-and-timeout-inside-ngonit-method