I have a debtService which calls backend API with simple HttpClient request. It returns an observable. Now, in AppComponent, I'm calling debtService's method to fetch debt. I want to make sure, that when debt is fetched, also the method called logGetDebtAttempt is being called.
import { Component } from '@angular/core';
import { Observable, Subject, Subscriber, TeardownLogic } from 'rxjs';
import { DebtService } from './services/debt.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private debtService: DebtService) {
}
async getDebt() {
// getNationalDebt() returns Observable<Number>
await this.debtService.getNationalDebt().toPromise();
this.logGetDebtAttempt();
}
logGetDebtAttempt() {
}
}
That's why I wrote such test:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { cold } from 'jasmine-marbles';
import { Observable, Subscriber, TeardownLogic } from 'rxjs';
import { AppComponent } from './app.component';
import { DebtService } from './services/debt.service';
import { HttpClientTestingModule } from '@angular/common/http/testing'
const chartServiceStub = {
getNationalDebt(): Observable<Number> {
return cold('--x|', { x: 1 });
}
};
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule,
HttpClientTestingModule
],
declarations: [
AppComponent
],
providers: [
{ provide: DebtService, useValue: chartServiceStub },
]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
});
it('should test', async () => {
spyOn(component, 'getDebt').and.callThrough();
spyOn(component, 'logGetDebtAttempt').and.callThrough();
await component.getDebt();
expect(component.logGetDebtAttempt).toHaveBeenCalled();
});
});
When running tests, await component.getDebt(); never ends and it creates a timeout.
Could someone please explain why is that happening?
Disclaimer: This won't completely answer your question.
I am thinking it happens because of the
--syntax where each dash is one millisecond.From my experience, I was never a fan of
jasmine-marblesor any marble testing helping library because of those dashes.For your scenario, you don't even need marbles. You can use
of.And also, since it is a
.toPromise, I would do atake(1)on it too. I think having thistake, it might help with the marbles scenario as well. I know this is an http call most likely and thetakeis not needed but you could argue that it is better design because if I am going to useawait, the stream cannot emit forever.