Skip to content

Commit

Permalink
feat: add generic and enumerable tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison committed Oct 23, 2024
1 parent 67bbd54 commit af906ff
Showing 1 changed file with 191 additions and 40 deletions.
231 changes: 191 additions & 40 deletions Refit.Tests/ReflectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,51 @@ public interface IBasicApi
[Get("/{value}")]
Task<string> GetGenericParam<T>(T value);

[Get("/")]
Task<string> GetQuery(string queryKey);

[Get("/")]
Task<string> GetGenericQuery<T>(T queryKey);

[Get("/")]
Task<string> GetPropertyQuery(BaseRecord queryKey);

[Get("/")]
Task<string> GetEnumerableQuery(IEnumerable<string> enums);

[Get("/")]
Task<string> GetEnumerablePropertyQuery(MyEnumerableParams enums);

[Get("/")]
Task<string> GetDictionaryQuery(IDictionary<string, object> dict);
}

public record DerivedRecordWithProperty(string Name) : BaseRecord("value");

public record DerivedRecord(string Value) : BaseRecord(Value);

public record BaseRecord(string Value);

public record MyParams(string PropValue);

public record MyEnumerableParams(int[] Enumerable);

public class TestUrlFormatter : IUrlParameterFormatter
{
private readonly ICustomAttributeProvider[] expectedAttributeProviders;
private readonly Type[] expectedTypes;
private int index = 0;
private int index;

public TestUrlFormatter(ICustomAttributeProvider expectedAttributeProvider, Type expectedType)
{
expectedAttributeProviders = [expectedAttributeProvider];
expectedTypes = [expectedType];
}

public TestUrlFormatter(ICustomAttributeProvider[] expectedAttributeProviders, Type[] expectedTypes)
public TestUrlFormatter(
ICustomAttributeProvider[] expectedAttributeProviders,
Type[] expectedTypes
)
{
this.expectedAttributeProviders = expectedAttributeProviders;
this.expectedTypes = expectedTypes;
Expand All @@ -55,7 +74,7 @@ public string Format(object value, ICustomAttributeProvider attributeProvider, T
Assert.Equal(expectedAttributeProviders[index], attributeProvider);
Assert.Equal(expectedTypes[index], type);
index++;
return value.ToString();
return value!.ToString();
}

public void AssertNoOutstandingAssertions()
Expand All @@ -73,16 +92,19 @@ public sealed class ReflectionTests : IDisposable
public async Task UrlParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/bar")
.Expect(HttpMethod.Get, "https://foo/bar")
.Respond("application/json", nameof(IBasicApi.GetParam));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetParam))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(string));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetParam("bar");
formatter.AssertNoOutstandingAssertions();
Expand All @@ -92,16 +114,19 @@ public async Task UrlParameterShouldBeExpectedReflection()
public async Task DerivedUrlParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/DerivedRecord%20%7B%20Value%20%3D%20Derived%20%7D")
.Expect(HttpMethod.Get, "https://foo/DerivedRecord%20%7B%20Value%20%3D%20Derived%20%7D")
.Respond("application/json", nameof(IBasicApi.GetDerivedParam));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetDerivedParam))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(BaseRecord));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetDerivedParam(new DerivedRecord("Derived"));
formatter.AssertNoOutstandingAssertions();
Expand All @@ -111,15 +136,18 @@ public async Task DerivedUrlParameterShouldBeExpectedReflection()
public async Task PropertyParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/propVal")
.Expect(HttpMethod.Get, "https://foo/propVal")
.Respond("application/json", nameof(IBasicApi.GetPropertyParam));

var propertyInfo = typeof(MyParams).GetProperties()[0];

var formatter = new TestUrlFormatter(propertyInfo, typeof(string));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetPropertyParam(new MyParams("propVal"));
formatter.AssertNoOutstandingAssertions();
Expand All @@ -129,42 +157,68 @@ public async Task PropertyParameterShouldBeExpectedReflection()
public async Task GenericParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/genericVal")
.Expect(HttpMethod.Get, "https://foo/genericVal")
.Respond("application/json", nameof(IBasicApi.GetGenericParam));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetGenericParam))!;
var stringMethod = methodInfo.MakeGenericMethod(typeof(string));
var parameterInfo = stringMethod.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(string));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetGenericParam("genericVal");
formatter.AssertNoOutstandingAssertions();
}

[Fact]
public async Task QueryPropertyParameterShouldBeExpectedReflection()
public async Task QueryParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/")
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(
new[]
{
new KeyValuePair<string, string>("Value", "queryVal"),
}
new[] { new KeyValuePair<string, string>("queryKey", "queryValue"), }
)
.Respond("application/json", nameof(IBasicApi.GetQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(string));
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetQuery("queryValue");
formatter.AssertNoOutstandingAssertions();
}

[Fact]
public async Task QueryPropertyParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(new[] { new KeyValuePair<string, string>("Value", "queryVal"), })
.Respond("application/json", nameof(IBasicApi.GetPropertyQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetPropertyQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(BaseRecord));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetPropertyQuery(new BaseRecord("queryVal"));
formatter.AssertNoOutstandingAssertions();
Expand All @@ -174,32 +228,118 @@ public async Task QueryPropertyParameterShouldBeExpectedReflection()
public async Task DerivedQueryPropertyParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/")
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(
new[]
{
new KeyValuePair<string, string>("Value", "queryVal"),
new KeyValuePair<string, string>("Name", "queryName"),
new KeyValuePair<string, string>("Value", "value"),
}
)
.Respond("application/json", nameof(IBasicApi.GetPropertyQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetPropertyQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(BaseRecord));
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var formatter = new TestUrlFormatter(
[parameterInfo, parameterInfo],
[typeof(BaseRecord), typeof(BaseRecord)]
);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetPropertyQuery(new DerivedRecordWithProperty("queryName"));
formatter.AssertNoOutstandingAssertions();
}

await service.GetPropertyQuery(new DerivedRecord("queryVal"));
[Fact]
public async Task GenericQueryParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(
new[] { new KeyValuePair<string, string>("queryKey", "queryValue"), }
)
.Respond("application/json", nameof(IBasicApi.GetGenericQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetGenericQuery))!;
var stringMethod = methodInfo.MakeGenericMethod(typeof(string));
var parameterInfo = stringMethod.GetParameters()[0];

var formatter = new TestUrlFormatter(parameterInfo, typeof(string));
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetGenericQuery("queryValue");
formatter.AssertNoOutstandingAssertions();
}

[Fact]
public async Task EnumerableQueryParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(new[] { new KeyValuePair<string, string>("enums", "k0,k1"), })
.Respond("application/json", nameof(IBasicApi.GetEnumerableQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetEnumerableQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter(
[parameterInfo, parameterInfo],
[typeof(IEnumerable<string>), typeof(IEnumerable<string>)]
);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetEnumerableQuery(["k0", "k1"]);
formatter.AssertNoOutstandingAssertions();
}

[Fact]
public async Task EnumerablePropertyQueryParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(new[] { new KeyValuePair<string, string>("Enumerable", "0,1"), })
.Respond("application/json", nameof(IBasicApi.GetEnumerablePropertyQuery));

var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetEnumerablePropertyQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];
var propertyInfo = typeof(MyEnumerableParams).GetProperties()[0];

var formatter = new TestUrlFormatter(
[propertyInfo, propertyInfo, parameterInfo],
[typeof(int[]), typeof(int[]), typeof(MyEnumerableParams)]
);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

await service.GetEnumerablePropertyQuery(new MyEnumerableParams([0, 1]));
formatter.AssertNoOutstandingAssertions();
}

[Fact]
public async Task QueryDictionaryParameterShouldBeExpectedReflection()
{
mockHandler
.Expect(HttpMethod.Get, "http://foo/")
.Expect(HttpMethod.Get, "https://foo/")
.WithExactQueryString(
new[]
{
Expand All @@ -212,10 +352,21 @@ public async Task QueryDictionaryParameterShouldBeExpectedReflection()
var methodInfo = typeof(IBasicApi).GetMethod(nameof(IBasicApi.GetDictionaryQuery))!;
var parameterInfo = methodInfo.GetParameters()[0];

var formatter = new TestUrlFormatter([typeof(string), typeof(string), parameterInfo, parameterInfo], [typeof(string), typeof(string), typeof(IDictionary<string, object>),typeof(IDictionary<string, object>)]);
var settings = new RefitSettings() { HttpMessageHandlerFactory = () => mockHandler };
settings.UrlParameterFormatter = formatter;
var service = RestService.For<IBasicApi>("http://foo", settings);
var formatter = new TestUrlFormatter(
[typeof(string), typeof(string), parameterInfo, parameterInfo],
[
typeof(string),
typeof(string),
typeof(IDictionary<string, object>),
typeof(IDictionary<string, object>)
]
);
var settings = new RefitSettings
{
HttpMessageHandlerFactory = () => mockHandler,
UrlParameterFormatter = formatter
};
var service = RestService.For<IBasicApi>("https://foo", settings);

var dict = new Dictionary<string, object> { { "key0", 1 }, { "key1", 2 } };
await service.GetDictionaryQuery(dict);
Expand Down

0 comments on commit af906ff

Please sign in to comment.