1

I am trying to test that http params are correct when I make a http request.

When I do expect(req.request.params.get('action')).toEqual('pause'); the test fails:

Expected: "pause" Received: null

Service

constructor(private _http: HttpClient)

pause(key: string): Observable<ReturnValue> {
    const httpParams = new HttpParams().set('action', 'pause');

    return this._http
        .put<ReturnValue>(`${API.pauseUrl}/${key}`, {
        params: httpParams,
    });
}

Test

let httpMock: HttpTestingController;
let httpClient: HttpClient;
let service: MyService;

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    providers: [MyService],
  }).compileComponents();

  httpMock = TestBed.inject(HttpTestingController);
  httpClient = TestBed.inject(HttpClient);
  service = TestBed.inject(MyService);
});

afterEach(() => {
  httpMock.verify();
});

describe("WHEN: pause", () => {
  const key = "1q2w3e-4r5t6y";
  const response: ReturnValue = ({
    key,
    status: "paused",
  } as ReturnValue;

  it("THEN: should call http.put with the expected url and params", (done) => {
      service.pause(key).subscribe(() => {
        expect(req.request.method).toBe('PUT');
        expect(req.request.params.get('action')).toEqual('pause');
        expect(req.request.url).toBe(`${PUSH_CORE_API.parcelUrl}/${key}`);
        done();
      });
      const req = httpMock.expectOne({
        method: 'PUT',
        url: `${PUSH_CORE_API.parcelUrl}/${key}`,
      });
      req.flush(response);
  });
});

Any ideas why this happens?

I am using Angular with Jest and TestBed for this test.

adrisons
  • 3,443
  • 3
  • 32
  • 48
  • 1
    The request is asynchronous, and `expect(req.request.params.get("action")).toEqual("pause");` runs before the mocked request itself was made. Could try to put the three `expect` statements after `flush` in the lambda of `subscribe` method? This way they will be evaulated definatelly after the mocked request is finished. I'm not 100% sure, that this is the root of the problem, but it is worth a try. – Milan Tenk Apr 13 '20 at 11:18
  • Thanks for the comment! `flush` has to be out of the lambda, or the subscription will never receive a value. I've updated the question putting the expect statements inside the subscribe lambda. httpParam is still received as "null" – adrisons Apr 13 '20 at 13:57

2 Answers2

4

Had a similar issue. Hopefully this helps someone in the future.

it('THEN: should call http.put with the expected url and params', (done) => {
    service.pause(key).subscribe(() => done());

    const expectedRequest = httpBackend
        .expectOne(r => r.url === `${API.pauseUrl}/${key}`);

    expectedRequest.flush(response);
    expect(expectedRequest.request.url).toBe(`${API.pauseUrl}/${key}`);
    expect(expectedRequest.request.method).toBe('PUT');
    expect(expectedRequest.request.params.get('action')).toEqual('pause');
});
3

You can do your test like so :

it("THEN: should call http.put with the expected url and params", (done) => {
    service.pause(key).subscribe(() => done());

      httpMock
      .expectOne((req: HttpRequest<any>) => {

         expect(rep.url).toBe(`${API.pauseUrl}/${key}`);        
         expect(req.method).toBe('PUT');
         expect(req.params.get('action')).toEqual('pause');
         expect(req.url).toBe(`${API.pauseUrl}/${key}`);

        return true;
      })
      .flush(response);
  });
});

hope it helps you