Error: Expected no open requests, found 1
I am getting this error when I try to execute HTTP unit test cases.
I am using Angular 5. How can I resolve this?
Below is my code for normal GET. Below code just brings normal GET.
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController, TestRequest } from
'@angular/common/http/testing';
import { DangerService } from './danger.service';
import { DangerFlag } from '../danger.model';
describe('DataService Tests', () => {
let dataService: DangerService;
let httpTestingController: HttpTestingController;
let testDangerFlags: DangerFlag[] = [ "sample data" ]
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule ],
providers: [ DangerService ]
});
dataService = TestBed.get(DangerService);
httpTestingController = TestBed.get(HttpTestingController);
});
afterEach(() => {
httpTestingController.verify();
});
fit('should get all danger flags', () => {
dataService.getDangerFlagDetails()
.subscribe((data: DangerFlag[]) => {
expect(data.length).toBe(3);
});
});
});
Solution 1:
Expected no open requests, found 1
This happens when you make a mock request, but don't 'complete/close' it. An open request may stay open after a test is run, eventually memory leaking, especially if the test is ran multiple times.
Subscribing to a mock request calls it as far as the client side is concerned but does not 'complete' it as far as the backend is concerned. 'Completing' a request can be done in a number of ways;
backend = TestBed.get(HttpTestingController)
-
backend.expectOne(URL)
- this will both test for a url, and 'close' the backend call. This will not test for params, and will fail if your query has params in it. -
backend.expectNone(URL)
- in case you're testing for urls that have params,expectOne()
wont work. You'll have to usebackend.match()
. Match does not auto close the backend api call, so you canexpectNone()
after it to close it out. -
.flush(RESPONSE)
- flush will force-send a response for the http call, and subsequently close the call. Note: if calling flush on amatch()
, watch out for match returning an array, i.e.backend.match(...)[0].flush({})
Any of these methods will close out the http request, and make backend.verify()
behave.
References
- You can find in depth examples, and more explanations here
-
expectOne()
andmatch()
return an instance of TestRequest -
expectNone()
always returnsvoid
Solution 2:
I also faced this issue today. Add expectOne function call
it('should get all danger flags', () => {
const actualDangerFlags = createDangerFlagResponse();
dataService.getDangerFlagDetails()
.subscribe((actualDangerFlags) => {
expect(data.length).toBe(3);
});
});
const httpRequest = httpTestingController.expectOne(BASE_URL + relativeURL);
expect(httpRequest.request.method).toBe('GET');
httpRequest.flush(actualDangerFlags);
});
createDangerFlagResponse(): DangerFlag[] {
return /* DangerFlag Array */
}