From a01cb84549007750e57c9e4328e1f43781dfa480 Mon Sep 17 00:00:00 2001 From: Tim M <49349513+TimothyMakkison@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:25:39 +0100 Subject: [PATCH] feat: add `RestServiceExceptions` (#1886) --- Refit.Tests/RestServiceExceptions.cs | 174 +++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 Refit.Tests/RestServiceExceptions.cs diff --git a/Refit.Tests/RestServiceExceptions.cs b/Refit.Tests/RestServiceExceptions.cs new file mode 100644 index 000000000..fabf5f0b1 --- /dev/null +++ b/Refit.Tests/RestServiceExceptions.cs @@ -0,0 +1,174 @@ +using Xunit; +// ReSharper disable InconsistentNaming + +namespace Refit.Tests; + +public interface IManyCancellationTokens +{ + [Get("/")] + Task GetValue(CancellationToken token0, CancellationToken token1); +} + +public interface IManyHeaderCollections +{ + [Get("/")] + Task GetValue([HeaderCollection] IDictionary collection0, [HeaderCollection] IDictionary collection1); +} + +public interface IHeaderCollectionWrongType +{ + [Get("/")] + Task GetValue([HeaderCollection] IDictionary collection); +} + +public interface IDoesNotStartSlash +{ + [Get("users")] + Task GetValue(); +} + +public interface IUrlContainsCRLF +{ + [Get("/\r")] + Task GetValue(); +} + +public interface IRoundTripNotString +{ + [Get("/{**value}")] + Task GetValue(int value); +} + +public interface IUrlNoMatchingParameters +{ + [Get("/{value}")] + Task GetValue(); +} + +public interface IMultipartAndBody +{ + [Get("/}")] + [Multipart] + Task GetValue([Body] string body); +} + +public interface IManyBody +{ + [Get("/")] + Task GetValue([Body] string body0, [Body] string body1); +} + +public class UserBody +{ + public string Value { get; set; } +} + +public interface IManyComplexTypes +{ + [Post("/")] + Task PostValue(UserBody body0, UserBody body1); +} + +public interface IManyAuthorize +{ + [Get("/")] + Task GetValue([Authorize("Bearer")] string token0, [Authorize("Bearer")] string token1); +} + +public interface IInvalidReturnType +{ + [Get("/")] + string GetValue(); +} + +public class RestServiceExceptionTests +{ + [Fact] + public void ManyCancellationTokensShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("only contain a single CancellationToken", exception); + } + + [Fact] + public void ManyHeaderCollectionShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("Only one parameter can be a HeaderCollection parameter", exception); + } + + [Fact] + public void InvalidHeaderCollectionTypeShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("HeaderCollection parameter of type", exception); + } + + [Fact] + public void UrlDoesntStartWithSlashShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("must start with '/' and be of the form", exception); + } + + [Fact] + public void UrlContainsCRLFShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("must not contain CR or LF characters", exception); + } + + [Fact] + public void RoundTripParameterNotStringShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("has round-tripping parameter", exception); + } + + [Fact] + public void UrlNoMatchingParameterShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("but no method parameter matches", exception); + } + + [Fact] + public void MultipartAndBodyShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("Multipart requests may not contain a Body parameter", exception); + } + + [Fact] + public void ManyBodyShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("Only one parameter can be a Body parameter", exception); + } + + [Fact] + public void ManyComplexTypesShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("Multiple complex types found. Specify one parameter as the body using BodyAttribute", exception); + } + + [Fact] + public void ManyAuthorizeAttributesShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("Only one parameter can be an Authorize parameter", exception); + } + + [Fact] + public void InvalidReturnTypeShouldThrow() + { + var exception = Assert.Throws(() => RestService.For("https://api.github.com")); + AssertExceptionContains("is invalid. All REST Methods must return either Task or ValueTask or IObservable", exception); + } + + private static void AssertExceptionContains(string expectedSubstring, Exception exception) + { + Assert.Contains(expectedSubstring, exception.Message!, StringComparison.Ordinal); + } +}