Skip to content

Commit a01cb84

Browse files
feat: add RestServiceExceptions (#1886)
1 parent b13cbf2 commit a01cb84

1 file changed

Lines changed: 174 additions & 0 deletions

File tree

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
using Xunit;
2+
// ReSharper disable InconsistentNaming
3+
4+
namespace Refit.Tests;
5+
6+
public interface IManyCancellationTokens
7+
{
8+
[Get("/")]
9+
Task<string> GetValue(CancellationToken token0, CancellationToken token1);
10+
}
11+
12+
public interface IManyHeaderCollections
13+
{
14+
[Get("/")]
15+
Task<string> GetValue([HeaderCollection] IDictionary<string, string> collection0, [HeaderCollection] IDictionary<string, string> collection1);
16+
}
17+
18+
public interface IHeaderCollectionWrongType
19+
{
20+
[Get("/")]
21+
Task<string> GetValue([HeaderCollection] IDictionary<string, object> collection);
22+
}
23+
24+
public interface IDoesNotStartSlash
25+
{
26+
[Get("users")]
27+
Task<string> GetValue();
28+
}
29+
30+
public interface IUrlContainsCRLF
31+
{
32+
[Get("/\r")]
33+
Task<string> GetValue();
34+
}
35+
36+
public interface IRoundTripNotString
37+
{
38+
[Get("/{**value}")]
39+
Task<string> GetValue(int value);
40+
}
41+
42+
public interface IUrlNoMatchingParameters
43+
{
44+
[Get("/{value}")]
45+
Task<string> GetValue();
46+
}
47+
48+
public interface IMultipartAndBody
49+
{
50+
[Get("/}")]
51+
[Multipart]
52+
Task<string> GetValue([Body] string body);
53+
}
54+
55+
public interface IManyBody
56+
{
57+
[Get("/")]
58+
Task<string> GetValue([Body] string body0, [Body] string body1);
59+
}
60+
61+
public class UserBody
62+
{
63+
public string Value { get; set; }
64+
}
65+
66+
public interface IManyComplexTypes
67+
{
68+
[Post("/")]
69+
Task<string> PostValue(UserBody body0, UserBody body1);
70+
}
71+
72+
public interface IManyAuthorize
73+
{
74+
[Get("/")]
75+
Task<string> GetValue([Authorize("Bearer")] string token0, [Authorize("Bearer")] string token1);
76+
}
77+
78+
public interface IInvalidReturnType
79+
{
80+
[Get("/")]
81+
string GetValue();
82+
}
83+
84+
public class RestServiceExceptionTests
85+
{
86+
[Fact]
87+
public void ManyCancellationTokensShouldThrow()
88+
{
89+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IManyCancellationTokens>("https://api.github.com"));
90+
AssertExceptionContains("only contain a single CancellationToken", exception);
91+
}
92+
93+
[Fact]
94+
public void ManyHeaderCollectionShouldThrow()
95+
{
96+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IManyHeaderCollections>("https://api.github.com"));
97+
AssertExceptionContains("Only one parameter can be a HeaderCollection parameter", exception);
98+
}
99+
100+
[Fact]
101+
public void InvalidHeaderCollectionTypeShouldThrow()
102+
{
103+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IHeaderCollectionWrongType>("https://api.github.com"));
104+
AssertExceptionContains("HeaderCollection parameter of type", exception);
105+
}
106+
107+
[Fact]
108+
public void UrlDoesntStartWithSlashShouldThrow()
109+
{
110+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IDoesNotStartSlash>("https://api.github.com"));
111+
AssertExceptionContains("must start with '/' and be of the form", exception);
112+
}
113+
114+
[Fact]
115+
public void UrlContainsCRLFShouldThrow()
116+
{
117+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IUrlContainsCRLF>("https://api.github.com"));
118+
AssertExceptionContains("must not contain CR or LF characters", exception);
119+
}
120+
121+
[Fact]
122+
public void RoundTripParameterNotStringShouldThrow()
123+
{
124+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IRoundTripNotString>("https://api.github.com"));
125+
AssertExceptionContains("has round-tripping parameter", exception);
126+
}
127+
128+
[Fact]
129+
public void UrlNoMatchingParameterShouldThrow()
130+
{
131+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IUrlNoMatchingParameters>("https://api.github.com"));
132+
AssertExceptionContains("but no method parameter matches", exception);
133+
}
134+
135+
[Fact]
136+
public void MultipartAndBodyShouldThrow()
137+
{
138+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IMultipartAndBody>("https://api.github.com"));
139+
AssertExceptionContains("Multipart requests may not contain a Body parameter", exception);
140+
}
141+
142+
[Fact]
143+
public void ManyBodyShouldThrow()
144+
{
145+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IManyBody>("https://api.github.com"));
146+
AssertExceptionContains("Only one parameter can be a Body parameter", exception);
147+
}
148+
149+
[Fact]
150+
public void ManyComplexTypesShouldThrow()
151+
{
152+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IManyComplexTypes>("https://api.github.com"));
153+
AssertExceptionContains("Multiple complex types found. Specify one parameter as the body using BodyAttribute", exception);
154+
}
155+
156+
[Fact]
157+
public void ManyAuthorizeAttributesShouldThrow()
158+
{
159+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IManyAuthorize>("https://api.github.com"));
160+
AssertExceptionContains("Only one parameter can be an Authorize parameter", exception);
161+
}
162+
163+
[Fact]
164+
public void InvalidReturnTypeShouldThrow()
165+
{
166+
var exception = Assert.Throws<ArgumentException>(() => RestService.For<IInvalidReturnType>("https://api.github.com"));
167+
AssertExceptionContains("is invalid. All REST Methods must return either Task<T> or ValueTask<T> or IObservable<T>", exception);
168+
}
169+
170+
private static void AssertExceptionContains(string expectedSubstring, Exception exception)
171+
{
172+
Assert.Contains(expectedSubstring, exception.Message!, StringComparison.Ordinal);
173+
}
174+
}

0 commit comments

Comments
 (0)