Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing - HttpTestingController throws errors for valid JSON #20690

Closed
klinki opened this issue Nov 29, 2017 · 20 comments
Closed

Testing - HttpTestingController throws errors for valid JSON #20690

klinki opened this issue Nov 29, 2017 · 20 comments

Comments

@klinki
Copy link

@klinki klinki commented Nov 29, 2017

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

HttpTestingController throws exception for valid JSON.
Failed: Automatic conversion to JSON is not supported for response type. error
(see https://github.com/angular/angular/blob/master/packages/common/http/testing/src/request.ts#L159)

But according to http://www.json.org/ valid JSON is:

  • array
  • object
  • string
  • number
  • null
  • true/false

Expected behavior

It should not throw exception and use value as JSON response of http call.

Minimal reproduction of the problem with instructions

const req = httpMock.expectOne('some-url');
req.flush(true);

Environment


Angular version: 5.0.2
@jabby
Copy link

@jabby jabby commented Jan 11, 2018

I'm encounter the same issue with angular in version 4.4.6.

Is there a workaround?

@scote
Copy link

@scote scote commented Jan 18, 2018

Any update on this issue? I have the same problem. My application run Angular 5.2.1.

@scote
Copy link

@scote scote commented Jan 22, 2018

I found a workaround. But i'm not sure if it is the best solution.

Here what I did until they fix it.

testService.isEnabled().subscribe((result: boolean) => {
  expect(result).toEqual(Observable.of(true));
});

const req = httpMock.expectOne('some-url');
req.flush(Obserbvable.of(true));

@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018
@jdell64
Copy link

@jdell64 jdell64 commented Jan 31, 2018

Your workaround gave me this:

error TS2345: Argument of type 'Observable<boolean>' is not assignable to parameter of type 'Expected<boolean>'.
  Type 'Observable<boolean>' is not assignable to type 'ObjectContaining<boolean>'.

@scote
Copy link

@scote scote commented Jan 31, 2018

Can you add a snippet of your code?

jdell64 pushed a commit to jdell64/angular that referenced this issue Jan 31, 2018
The flush method in TestRequest can return a boolean as this is a valid
json response.

Closes angular#20690
@jdell64
Copy link

@jdell64 jdell64 commented Jan 31, 2018

Sure... It is like this:

export const FLUSH_OK = {status: 200, statusText: 'Ok'};
// ... 
it('should work', async(() => {     
        service.myFunction().subscribe((data) => {
            expect(data).toEqual(Observable.of(true));
        });
       
    
     httpMock.expectOne((req) => {
            return req.url === MY_URL
        }).flush(Observable.of(true), FLUSH_OK);

}));

jdell64 added a commit to jdell64/angular that referenced this issue Jan 31, 2018
The flush method in TestRequest can return a boolean as this is a valid
json response.

Closes angular#20690
jdell64 added a commit to jdell64/angular that referenced this issue Jan 31, 2018
The flush method in TestRequest can return a boolean as this is a valid
json response.

Closes angular#20690
jdell64 added a commit to jdell64/angular that referenced this issue Jan 31, 2018
The flush method in TestRequest can return a boolean as this is a valid
json response.

Closes angular#20690
jdell64 added a commit to jdell64/angular that referenced this issue Jan 31, 2018
The flush method in TestRequest can return a boolean as this is a valid
json response.

Closes angular#20690
@jdell64
Copy link

@jdell64 jdell64 commented Jan 31, 2018

submitted a PR, but i doubt i did it right... one of the travis builds doesnt like me

@ngbot ngbot bot removed this from the Backlog milestone Feb 26, 2018
@ngbot ngbot bot added this to the needsTriage milestone Feb 26, 2018
@ngbot ngbot bot removed this from the needsTriage milestone Feb 28, 2018
@ngbot ngbot bot added this to the Backlog milestone Feb 28, 2018
@balane
Copy link

@balane balane commented Mar 30, 2018

this is super annoying. please get fix in soon

@sloosch
Copy link

@sloosch sloosch commented May 16, 2018

work-a-round:

const req = httpMock.expectOne('some-url');
req.event(new HttpResponse<boolean>({body: true}));

instead of req.flush(true)

@adamlarner
Copy link

@adamlarner adamlarner commented Jul 9, 2018

The above workaround simply masks the issue, since no response is actually resolved without calling 'flush' or 'error'. The reason it will appear to succeed is simply due to the specific nature of the testing scenario, for example:

it ("should verify that user is authenticated", () => {
    // calls underlying http post at 'api/account/isAuth'
    service.isAuth().then(response => {
      // does not execute, and so test defaults to success
      console.log("success!");
      expect(response).toBe(true);
    });

    const req = backend.expectOne("api/account/isAuth");
    req.event(new HttpResponse<boolean>({ body: true }));
  });

As stated in the docs, 'event' is used for sending HttpEvent responses for things like progress updates, and as such doesn't appear to have much use unless 'flush' or 'error' is used to call 'complete' or 'error' on the underlying observable.

The solution I used was simply to use a 'truthy' value in place of the boolean. Any underlying checks against a boolean value can usually be resolved within conditional statements this way, and so any logic checks in the underlying method code should be covered in this scenario:

it ("should verify that user is authenticated", () => {
    service.isAuth().then(response => {
      console.log("success!"); // underlying check successfully calls
      expect(response).toBe(true); // response is 'true', since underlying check against 1 is 'true'
    });

    const req = backend.expectOne("api/account/isAuth");
    // underlying post response body should be 'true', but 1 is truthy, and so will work in most scenarios
    req.flush(1); 
  });

Changing the one to zero in the above test causes the test to fail, and as such achieves the exact same behaviour as I would have expected from using a boolean value in the body of the response.

@Peter554
Copy link

@Peter554 Peter554 commented Dec 13, 2018

Any updates on if this is getting fixed?

@C0ZEN
Copy link

@C0ZEN C0ZEN commented Mar 27, 2019

I did not manage to find a solution with above comments.
2 years and no solution ?!

  • Angular 7.2.3

@Bloodypie
Copy link

@Bloodypie Bloodypie commented Apr 4, 2019

Maybe this will help anybody:
http.get<Object>(url, { responseType: 'blob' as 'json' })

@dwilches
Copy link

@dwilches dwilches commented Jul 16, 2019

I'm still seeing this issue. Any update?

@cjessing
Copy link

@cjessing cjessing commented Aug 22, 2019

Angular 8... same issue :-(

@menelikw
Copy link

@menelikw menelikw commented Sep 10, 2019

Should just be able to write: req.flush({ body: true })

@djmarquette
Copy link

@djmarquette djmarquette commented Mar 29, 2020

yes, this still is a problem. I could not get @adamlarner's solution to work (above) but was able to tweak with flushing a 0 or 1 and then having the test verify as:
expect(result).toBeTruthy();
for 0 and:
expect(result).toBeFalsy();
for the 1 test.

I am not sure this will pass muster, but would like to see the httpTestingController handle this more cleanly as well.

@tylerjamesmadsen
Copy link

@tylerjamesmadsen tylerjamesmadsen commented Apr 9, 2020

I also couldn't get @adamlarner's solution to work, but a simple modification of his workaround is to use double-not !! to convert the flushed number to a boolean:

service.isAuth().then(response => {
  expect(!!response).toBe(true);
});

Another alternative is to flush a string of 'true' (or 'false') req.flush('true'); and then compare strings:

service.isAuth().then(response => {
  expect(`${response}`).toBe('true');
});

@alxhub
Copy link
Contributor

@alxhub alxhub commented May 29, 2020

Confirmed as reported, and this should be an easy fix. Definitely an opportunity for a community PR (I see there is one, but it's a few years old - hopefully @jdell64 is still around!)

ajitsinghkaler added a commit to ajitsinghkaler/angular that referenced this issue Jul 2, 2020
boolean is a valid json but at present we cannot test Http request using boolean added support for boolean requests

Fixes angular#20690
ajitsinghkaler added a commit to ajitsinghkaler/angular that referenced this issue Jul 9, 2020
boolean is a valid json but at present we cannot test Http request using boolean added support for boolean requests

Fixes angular#20690
ajitsinghkaler added a commit to ajitsinghkaler/angular that referenced this issue Jul 30, 2020
boolean is a valid json but at present we cannot test Http request using boolean added support for boolean requests

Fixes angular#20690
ajitsinghkaler added a commit to ajitsinghkaler/angular that referenced this issue Jul 30, 2020
boolean is a valid json but at present we cannot test Http request using boolean added support for boolean requests

Fixes angular#20690
@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Nov 6, 2020

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet