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

NullReferenceException if returned Content is null and success status code #60

Open
dpakpaul opened this issue Dec 16, 2015 · 4 comments

Comments

@dpakpaul
Copy link

Using the latest 3.0.1 version of Portable Rest.

When I call SendAsync() that does a PUT request, I get back a 400 Bad Request by the Portable Rest library. However, I had Fiddler running and I can see that the request actually succeeded (200) and there was no content returned.

Digging in to the source , it seems to me that the exception occurs in this method when it does a response.Content.ReadAsStringAsync() if Content is null -

In RestClient.cs -

private static async Task GetRawResponseContent([NotNull] HttpResponseMessage response)
{
//RWM: Explicitly check for NoContent... because the request was successful but there is nothing to do.
if (response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.NoContent)
{
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
return null;
}

@mikescott8
Copy link

just was writing a unit test where the mocked HttpMessageHandler I had set the response code to success (200) but not setting the content, and I was getting this error as well. I finally tracked down the method causing the issue and came to write up the issue, but found it's already here. So just adding on this would be nice to be fixed.

Defensive checks should be around it, in case some service returns back a good code but not a NoContent code and no content.

@robertmclaws
Copy link
Collaborator

Thanks for pointing this out, and sorry I missed it. I will see about getting a fix out today, and adding some unit tests.

@robertmclaws
Copy link
Collaborator

robertmclaws commented Jan 1, 2017

@mikescott8, can you please post the unit test you used to recreate this scenario?

Thanks!

@mikescott8
Copy link

Below are two tests, the differences are in the Asserts and ONE LINE in the Arrange. The one line missing is the setting the Content in the HttpResponseMessage.

Hope these are enough to help you build tests that you need/want.

    [TestMethod]
    public void PortableRestClient_SendsBackBadRequest_When200CodeIsSetButNoContent()
    {
        var sut = new PortableRest.RestClient
        {
            BaseUrl = "http://test.com/"
        };
        var handler = new Mock<HttpMessageHandler>();

        handler.Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
            .Returns(() => Task.FromResult(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK
            }));
        sut.HttpHandler = handler.Object;

        // act
        var restRequest = new RestRequest
        {
            Resource = "/",
            Method = HttpMethod.Get,
        };
        var response =
            sut.SendAsync<string>(restRequest)
                .Result;

        // assert 
        response.Exception.Should().NotBeNull();
        response.HttpResponseMessage.StatusCode.Should().Be(HttpStatusCode.BadRequest);
    }

    [TestMethod]
    public void PortableRestClient_SendsContent_When200CodeIsSetAndContent()
    {
        var sut = new PortableRest.RestClient
        {
            BaseUrl = "http://test.com/"
        };
        var handler = new Mock<HttpMessageHandler>();

        handler.Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
            .Returns(() => Task.FromResult(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("Good response.")
            }));
        sut.HttpHandler = handler.Object;

        // act
        var restRequest = new RestRequest
        {
            Resource = "/",
            Method = HttpMethod.Get,
        };
        var response =
            sut.SendAsync<string>(restRequest)
                .Result;

        // assert 
        response.Exception.Should().BeNull();
        response.HttpResponseMessage.StatusCode.Should().Be(HttpStatusCode.OK);
        response.HttpResponseMessage.Content.As<StringContent>().ReadAsStringAsync().Result.Should().Be("Good response.");
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants