Skip to content

Commit

Permalink
fix(Caller): Fix Caller does not support response value as null (#222)
Browse files Browse the repository at this point in the history
* fix(Caller): Fix Caller does not support response value as null

* test: Modify unit tests

* test: Modify unit tests
  • Loading branch information
zhenlei520 authored Aug 29, 2022
1 parent 5f53d23 commit 95880c5
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public DefaultResponseMessage(IOptions<CallerFactoryOptions> options, ILogger<De
public async Task<TResponse?> ProcessResponseAsync<TResponse>(HttpResponseMessage response,
CancellationToken cancellationToken = default)
{
var responseType = typeof(TResponse);
if (response.IsSuccessStatusCode)
{
switch (response.StatusCode)
Expand All @@ -27,31 +28,38 @@ public DefaultResponseMessage(IOptions<CallerFactoryOptions> options, ILogger<De
case (HttpStatusCode)MasaHttpStatusCode.UserFriendlyException:
throw new UserFriendlyException(await response.Content.ReadAsStringAsync(cancellationToken));
default:
if (typeof(TResponse) == typeof(Guid) || typeof(TResponse) == typeof(Guid?))
if (responseType == typeof(Guid) || responseType == typeof(Guid?))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
if (string.IsNullOrEmpty(content))
return (TResponse)(object?)null!;
var content = (await response.Content.ReadAsStringAsync(cancellationToken)).Replace("\"", "");
if (IsNullOrEmpty(content))
return default;

return (TResponse?)(object)Guid.Parse(content.Replace("\"", ""));
return (TResponse?)(object)Guid.Parse(content);
}
if (typeof(TResponse) == typeof(DateTime) || typeof(TResponse) == typeof(DateTime?))
if (responseType == typeof(DateTime) || responseType == typeof(DateTime?))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
if (string.IsNullOrEmpty(content))
return (TResponse)(object?)null!;
var content = (await response.Content.ReadAsStringAsync(cancellationToken)).Replace("\"", "");
if (IsNullOrEmpty(content))
return default;

return (TResponse?)(object)DateTime.Parse(content.Replace("\"", ""));
return (TResponse?)(object)DateTime.Parse(content);
}
if (typeof(TResponse).GetInterfaces().Any(type => type == typeof(IConvertible)))
if (responseType.GetInterfaces().Any(type => type == typeof(IConvertible)) ||
(responseType.IsGenericType && responseType.GenericTypeArguments.Length == 1 && responseType
.GenericTypeArguments[0].GetInterfaces().Any(type => type == typeof(IConvertible))))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
return (TResponse)Convert.ChangeType(content, typeof(TResponse));
if (IsNullOrEmpty(content))
return default;

if (responseType.IsGenericType)
return (TResponse?)Convert.ChangeType(content, responseType.GenericTypeArguments[0]);

return (TResponse?)Convert.ChangeType(content, responseType);
}
try
{
return await response.Content.ReadFromJsonAsync<TResponse>(_options.JsonSerializerOptions, cancellationToken)
?? throw new ArgumentException("The response cannot be empty or there is an error in deserialization");
return await response.Content.ReadFromJsonAsync<TResponse>(_options.JsonSerializerOptions, cancellationToken);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -89,4 +97,6 @@ public async Task ProcessResponseExceptionAsync(HttpResponseMessage response, Ca

throw new MasaException($"ReasonPhrase: {response.ReasonPhrase ?? string.Empty}, StatusCode: {response.StatusCode}");
}

private static bool IsNullOrEmpty(string value) => string.IsNullOrEmpty(value) || value == "null";
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public DefaultXmlResponseMessage(ILogger<DefaultResponseMessage>? logger = null)
public async Task<TResponse?> ProcessResponseAsync<TResponse>(HttpResponseMessage response,
CancellationToken cancellationToken = default)
{
var responseType = typeof(TResponse);
if (response.IsSuccessStatusCode)
{
switch (response.StatusCode)
Expand All @@ -25,32 +26,39 @@ public DefaultXmlResponseMessage(ILogger<DefaultResponseMessage>? logger = null)
case (HttpStatusCode)MasaHttpStatusCode.UserFriendlyException:
throw new UserFriendlyException(await response.Content.ReadAsStringAsync(cancellationToken));
default:
if (typeof(TResponse) == typeof(Guid) || typeof(TResponse) == typeof(Guid?))
if (responseType == typeof(Guid) || responseType == typeof(Guid?))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
if (string.IsNullOrEmpty(content))
return (TResponse)(object?)null!;
var content = (await response.Content.ReadAsStringAsync(cancellationToken)).Replace("\"", "");
if (IsNullOrEmpty(content))
return default;

return (TResponse?)(object)Guid.Parse(content.Replace("\"", ""));
return (TResponse?)(object)Guid.Parse(content);
}
if (typeof(TResponse) == typeof(DateTime) || typeof(TResponse) == typeof(DateTime?))
if (responseType == typeof(DateTime) || responseType == typeof(DateTime?))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
if (string.IsNullOrEmpty(content))
return (TResponse)(object?)null!;
var content = (await response.Content.ReadAsStringAsync(cancellationToken)).Replace("\"", "");
if (IsNullOrEmpty(content))
return default;

return (TResponse?)(object)DateTime.Parse(content.Replace("\"", ""));
return (TResponse?)(object)DateTime.Parse(content);
}
if (typeof(TResponse).GetInterfaces().Any(type => type == typeof(IConvertible)))
if (responseType.GetInterfaces().Any(type => type == typeof(IConvertible)) ||
(responseType.IsGenericType && responseType.GenericTypeArguments.Length == 1 && responseType
.GenericTypeArguments[0].GetInterfaces().Any(type => type == typeof(IConvertible))))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
return (TResponse)Convert.ChangeType(content, typeof(TResponse));
if (IsNullOrEmpty(content))
return default;

if (responseType.IsGenericType)
return (TResponse?)Convert.ChangeType(content, responseType.GenericTypeArguments[0]);

return (TResponse?)Convert.ChangeType(content, responseType);
}
try
{
var res = await response.Content.ReadAsStringAsync(cancellationToken);
return XmlUtils.Deserialize<TResponse>(res) ??
throw new ArgumentException("The response cannot be empty or there is an error in deserialization");
return XmlUtils.Deserialize<TResponse>(res);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -88,4 +96,6 @@ public async Task ProcessResponseExceptionAsync(HttpResponseMessage response, Ca

throw new MasaException($"ReasonPhrase: {response.ReasonPhrase ?? string.Empty}, StatusCode: {response.StatusCode}");
}

private static bool IsNullOrEmpty(string value) => string.IsNullOrEmpty(value) || value == "null";
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,105 @@ public async Task TestRequestMessageReturnOnceAsync()
Assert.IsTrue(res.Code == response.Code);
requestMessage.Verify(r => r.ProcessHttpRequestMessageAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<object>()), Times.Once);
}

[TestMethod]
public async Task TestResponseAsync()
{
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("null")
};
var services = new ServiceCollection();
services.Configure<CallerFactoryOptions>(option =>
{
option.JsonSerializerOptions = new JsonSerializerOptions();
});
var serviceProvider = services.BuildServiceProvider();
var defaultResponseMessage = new DefaultResponseMessage(serviceProvider.GetRequiredService<IOptions<CallerFactoryOptions>>());
Assert.IsNull(await defaultResponseMessage.ProcessResponseAsync<object?>(httpResponseMessage));

Assert.IsNull(await defaultResponseMessage.ProcessResponseAsync<int?>(httpResponseMessage));

Assert.IsNull(await defaultResponseMessage.ProcessResponseAsync<Guid?>(httpResponseMessage));

Assert.IsNull(await defaultResponseMessage.ProcessResponseAsync<DateTime?>(httpResponseMessage));

Assert.IsTrue(await defaultResponseMessage.ProcessResponseAsync<int>(httpResponseMessage) == 0);
Assert.IsTrue(await defaultResponseMessage.ProcessResponseAsync<Guid>(httpResponseMessage) == default);
Assert.IsTrue(await defaultResponseMessage.ProcessResponseAsync<DateTime>(httpResponseMessage) == default);
}

[TestMethod]
public async Task TestResponseIsIntAsync()
{
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(1.ToString())
};
var services = new ServiceCollection();
services.Configure<CallerFactoryOptions>(option =>
{
option.JsonSerializerOptions = new JsonSerializerOptions();
});
var serviceProvider = services.BuildServiceProvider();
var defaultResponseMessage = new DefaultResponseMessage(serviceProvider.GetRequiredService<IOptions<CallerFactoryOptions>>());

var res = await defaultResponseMessage.ProcessResponseAsync<int>(httpResponseMessage);
Assert.IsNotNull(res);
Assert.IsTrue(res == 1);

var res2 = await defaultResponseMessage.ProcessResponseAsync<int?>(httpResponseMessage);
Assert.IsNotNull(res2);
Assert.IsTrue(res2 == 1);
}

[TestMethod]
public async Task TestResponseIsGuidAsync()
{
Guid id = Guid.NewGuid();
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(id.ToString())
};
var services = new ServiceCollection();
services.Configure<CallerFactoryOptions>(option =>
{
option.JsonSerializerOptions = new JsonSerializerOptions();
});
var serviceProvider = services.BuildServiceProvider();
var defaultResponseMessage = new DefaultResponseMessage(serviceProvider.GetRequiredService<IOptions<CallerFactoryOptions>>());

var res = await defaultResponseMessage.ProcessResponseAsync<Guid?>(httpResponseMessage);
Assert.IsNotNull(res);
Assert.IsTrue(res == id);

var res2 = await defaultResponseMessage.ProcessResponseAsync<Guid>(httpResponseMessage);
Assert.IsNotNull(res2);
Assert.IsTrue(res2 == id);
}

[TestMethod]
public async Task TestResponseIsDateTimeAsync()
{
var date = DateTime.Now;
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(date.ToString("yyyy-MM-dd HH:mm:ss"))
};
var services = new ServiceCollection();
services.Configure<CallerFactoryOptions>(option =>
{
option.JsonSerializerOptions = new JsonSerializerOptions();
});
var serviceProvider = services.BuildServiceProvider();
var defaultResponseMessage = new DefaultResponseMessage(serviceProvider.GetRequiredService<IOptions<CallerFactoryOptions>>());

var res = await defaultResponseMessage.ProcessResponseAsync<DateTime?>(httpResponseMessage);
Assert.IsNotNull(res);
Assert.IsTrue(res.Value.ToString("yyyy-MM-dd HH:mm:ss") == date.ToString("yyyy-MM-dd HH:mm:ss"));

var res2 = await defaultResponseMessage.ProcessResponseAsync<DateTime>(httpResponseMessage);
Assert.IsNotNull(res2);
Assert.IsTrue(res2.ToString("yyyy-MM-dd HH:mm:ss") == date.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

global using Masa.BuildingBlocks.Service.Caller;
global using Masa.BuildingBlocks.Service.Caller.Options;
global using Masa.Contrib.Service.Caller.DaprClient;
global using Masa.Contrib.Service.Caller.HttpClient;
global using Masa.Contrib.Service.Caller.Tests.Queries;
Expand All @@ -11,6 +12,7 @@
global using Microsoft.AspNetCore.Builder;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Options;
global using Microsoft.VisualStudio.TestTools.UnitTesting;
global using Moq;
global using Moq.Protected;
Expand All @@ -19,5 +21,6 @@
global using System.Reflection;
global using System.Runtime.ExceptionServices;
global using System.Text;
global using System.Text.Json;
global using System.Text.Json.Serialization;
global using System.Xml.Serialization;

0 comments on commit 95880c5

Please sign in to comment.