solrevdev/instagram-basic-display

GetJsonAsync does not handle errors from Instagram.

Closed this issue · 0 comments

Describe the bug

When various methods call GetJsonAsync() they all expect the correct JSON to be returned.

Exceptions or where IsSuccessStatusCode == false are caught and logged but any JSON that does not match is not handled gracefully.

To Reproduce

Create a new file in the tests project

IGApiException.json

{
    "error": {
        "message": "Unsupported get request. Object with ID '3518610791' does not exist, cannot be loaded due to missing permissions, or does not support this operation",
        "type": "IGApiException",
        "code": 100,
        "error_subcode": 33,
        "fbtrace_id": "AZtb-9k2P_mHdfRi-sN4MNH"
    }
}

Amend InstagramApiTests.cs with this new test and small refactor

InstagramApiTests.cs

[Fact]
public async Task IGApiException_Is_Handled()
{
    // Arrange
    var credentials = MockInstagramCredentials();
    var options = Options.Create(credentials);
    var logger = Mock.Of<ILogger<InstagramApi>>();
    var mockFactory = MockHttpClientFactory_For_IGApiException();
    var instagramHttpClient = new InstagramHttpClient(options, mockFactory.Object, logger);
    var oAuthResponse = new OAuthResponse
    {
        AccessToken = "123",
        User = new UserInfo
        {
            Id = "123",
            Username = "solrevdev"
        }
    };

    // Act
    var api = new InstagramApi(options, logger, instagramHttpClient);
    var response = await api.GetMediaListAsync(oAuthResponse).ConfigureAwait(false);

    // Assert
    Assert.NotNull(api);
    Assert.NotNull(response);
    Assert.NotNull(response.Paging);
    Assert.NotNull(response.Data);
}

private static Mock<IHttpClientFactory> MockHttpClientFactory_For_GetMediaList()
{
    return MockHttpClientFactory_With_Json("GetMediaListAsync.json");
}

private static Mock<IHttpClientFactory> MockHttpClientFactory_For_IGApiException()
{
    return MockHttpClientFactory_With_Json("IGApiException.json");
}

private static Mock<IHttpClientFactory> MockHttpClientFactory_With_Json(string file)
{
    var mockFactory = new Mock<IHttpClientFactory>();
    var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
    var content = LoadFromFile(file);

    mockHttpMessageHandler.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(content),
        });

    var client = new HttpClient(mockHttpMessageHandler.Object);
    mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);
    return mockFactory;
}

Expected behaviour

Perhaps GetJsonAsync() should throw a custom InstagramApiException with all the error details if it encounters "error" in the response string instead of just returning T without any hydrated properties?

Needs some thought.