Skip to content

Commit eca6d76

Browse files
committed
Fix inconsistencies in test assertions
1 parent 8abd60d commit eca6d76

File tree

2 files changed

+284
-204
lines changed

2 files changed

+284
-204
lines changed

test/OpenApiKiotaEndToEndTests/ModelStateValidation/ModelStateValidationTests.cs

Lines changed: 142 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Net;
12
using FluentAssertions;
23
using Microsoft.Extensions.DependencyInjection;
34
using Microsoft.Kiota.Http.HttpClientLibrary;
@@ -59,14 +60,17 @@ public async Task Cannot_exceed_length_constraint(string firstName)
5960
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
6061

6162
// Assert
62-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
63-
response.Errors.Should().HaveCount(1);
64-
65-
ErrorObject errorObject = response.Errors.First();
66-
errorObject.Title.Should().Be("Input validation failed.");
67-
errorObject.Detail.Should().Be("The field FirstName must be a string or collection type with a minimum length of '2' and maximum length of '20'.");
68-
errorObject.Source.Should().NotBeNull();
69-
errorObject.Source.Pointer.Should().Be("/data/attributes/firstName");
63+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
64+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
65+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
66+
exception.Errors.Should().HaveCount(1);
67+
68+
ErrorObject error = exception.Errors[0];
69+
error.Status.Should().Be("422");
70+
error.Title.Should().Be("Input validation failed.");
71+
error.Detail.Should().Be("The field FirstName must be a string or collection type with a minimum length of '2' and maximum length of '20'.");
72+
error.Source.Should().NotBeNull();
73+
error.Source.Pointer.Should().Be("/data/attributes/firstName");
7074
}
7175

7276
[Theory]
@@ -97,14 +101,17 @@ public async Task Cannot_exceed_string_length_constraint(string userName)
97101
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
98102

99103
// Assert
100-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
101-
response.Errors.Should().HaveCount(1);
102-
103-
ErrorObject errorObject = response.Errors.First();
104-
errorObject.Title.Should().Be("Input validation failed.");
105-
errorObject.Detail.Should().Be("The field UserName must be a string with a minimum length of 3 and a maximum length of 18.");
106-
errorObject.Source.Should().NotBeNull();
107-
errorObject.Source.Pointer.Should().Be("/data/attributes/userName");
104+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
105+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
106+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
107+
exception.Errors.Should().HaveCount(1);
108+
109+
ErrorObject error = exception.Errors[0];
110+
error.Status.Should().Be("422");
111+
error.Title.Should().Be("Input validation failed.");
112+
error.Detail.Should().Be("The field UserName must be a string with a minimum length of 3 and a maximum length of 18.");
113+
error.Source.Should().NotBeNull();
114+
error.Source.Pointer.Should().Be("/data/attributes/userName");
108115
}
109116

110117
[Fact]
@@ -133,14 +140,17 @@ public async Task Cannot_violate_regular_expression_constraint()
133140
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
134141

135142
// Assert
136-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
137-
response.Errors.Should().HaveCount(1);
138-
139-
ErrorObject errorObject = response.Errors.First();
140-
errorObject.Title.Should().Be("Input validation failed.");
141-
errorObject.Detail.Should().Be("Only letters are allowed.");
142-
errorObject.Source.Should().NotBeNull();
143-
errorObject.Source.Pointer.Should().Be("/data/attributes/userName");
143+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
144+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
145+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
146+
exception.Errors.Should().HaveCount(1);
147+
148+
ErrorObject error = exception.Errors[0];
149+
error.Status.Should().Be("422");
150+
error.Title.Should().Be("Input validation failed.");
151+
error.Detail.Should().Be("Only letters are allowed.");
152+
error.Source.Should().NotBeNull();
153+
error.Source.Pointer.Should().Be("/data/attributes/userName");
144154
}
145155

146156
[Fact]
@@ -169,14 +179,17 @@ public async Task Cannot_use_invalid_credit_card_number()
169179
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
170180

171181
// Assert
172-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
173-
response.Errors.Should().HaveCount(1);
174-
175-
ErrorObject errorObject = response.Errors.First();
176-
errorObject.Title.Should().Be("Input validation failed.");
177-
errorObject.Detail.Should().Be("The CreditCard field is not a valid credit card number.");
178-
errorObject.Source.Should().NotBeNull();
179-
errorObject.Source.Pointer.Should().Be("/data/attributes/creditCard");
182+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
183+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
184+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
185+
exception.Errors.Should().HaveCount(1);
186+
187+
ErrorObject error = exception.Errors[0];
188+
error.Status.Should().Be("422");
189+
error.Title.Should().Be("Input validation failed.");
190+
error.Detail.Should().Be("The CreditCard field is not a valid credit card number.");
191+
error.Source.Should().NotBeNull();
192+
error.Source.Pointer.Should().Be("/data/attributes/creditCard");
180193
}
181194

182195
[Fact]
@@ -205,14 +218,17 @@ public async Task Cannot_use_invalid_email_address()
205218
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
206219

207220
// Assert
208-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
209-
response.Errors.Should().HaveCount(1);
210-
211-
ErrorObject errorObject = response.Errors.First();
212-
errorObject.Title.Should().Be("Input validation failed.");
213-
errorObject.Detail.Should().Be("The Email field is not a valid e-mail address.");
214-
errorObject.Source.Should().NotBeNull();
215-
errorObject.Source.Pointer.Should().Be("/data/attributes/email");
221+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
222+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
223+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
224+
exception.Errors.Should().HaveCount(1);
225+
226+
ErrorObject error = exception.Errors[0];
227+
error.Status.Should().Be("422");
228+
error.Title.Should().Be("Input validation failed.");
229+
error.Detail.Should().Be("The Email field is not a valid e-mail address.");
230+
error.Source.Should().NotBeNull();
231+
error.Source.Pointer.Should().Be("/data/attributes/email");
216232
}
217233

218234
[Fact]
@@ -242,16 +258,19 @@ public async Task Cannot_exceed_min_length_constraint()
242258
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
243259

244260
// Assert
245-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
246-
response.Errors.Should().HaveCount(1);
261+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
262+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
263+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
264+
exception.Errors.Should().HaveCount(1);
247265

248266
const int minCharsInBase64 = SocialMediaAccount.MinPasswordCharsInBase64;
249267

250-
ErrorObject errorObject = response.Errors.First();
251-
errorObject.Title.Should().Be("Input validation failed.");
252-
errorObject.Detail.Should().Be($"The field Password must be a string or array type with a minimum length of '{minCharsInBase64}'.");
253-
errorObject.Source.Should().NotBeNull();
254-
errorObject.Source.Pointer.Should().Be("/data/attributes/password");
268+
ErrorObject error = exception.Errors[0];
269+
error.Status.Should().Be("422");
270+
error.Title.Should().Be("Input validation failed.");
271+
error.Detail.Should().Be($"The field Password must be a string or array type with a minimum length of '{minCharsInBase64}'.");
272+
error.Source.Should().NotBeNull();
273+
error.Source.Pointer.Should().Be("/data/attributes/password");
255274
}
256275

257276
[Fact]
@@ -280,16 +299,19 @@ public async Task Cannot_exceed_max_length_constraint()
280299
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
281300

282301
// Assert
283-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
284-
response.Errors.Should().HaveCount(1);
302+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
303+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
304+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
305+
exception.Errors.Should().HaveCount(1);
285306

286307
const int maxCharsInBase64 = SocialMediaAccount.MaxPasswordCharsInBase64;
287308

288-
ErrorObject errorObject = response.Errors.First();
289-
errorObject.Title.Should().Be("Input validation failed.");
290-
errorObject.Detail.Should().Be($"The field Password must be a string or array type with a maximum length of '{maxCharsInBase64}'.");
291-
errorObject.Source.Should().NotBeNull();
292-
errorObject.Source.Pointer.Should().Be("/data/attributes/password");
309+
ErrorObject error = exception.Errors[0];
310+
error.Status.Should().Be("422");
311+
error.Title.Should().Be("Input validation failed.");
312+
error.Detail.Should().Be($"The field Password must be a string or array type with a maximum length of '{maxCharsInBase64}'.");
313+
error.Source.Should().NotBeNull();
314+
error.Source.Pointer.Should().Be("/data/attributes/password");
293315
}
294316

295317
[Theory]
@@ -322,14 +344,17 @@ public async Task Cannot_use_double_outside_of_valid_range(double age)
322344
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
323345

324346
// Assert
325-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
326-
response.Errors.Should().HaveCount(1);
327-
328-
ErrorObject errorObject = response.Errors.First();
329-
errorObject.Title.Should().Be("Input validation failed.");
330-
errorObject.Detail.Should().Be($"The field Age must be between {0.1} exclusive and {122.9} exclusive.");
331-
errorObject.Source.Should().NotBeNull();
332-
errorObject.Source.Pointer.Should().Be("/data/attributes/age");
347+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
348+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
349+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
350+
exception.Errors.Should().HaveCount(1);
351+
352+
ErrorObject error = exception.Errors[0];
353+
error.Status.Should().Be("422");
354+
error.Title.Should().Be("Input validation failed.");
355+
error.Detail.Should().Be($"The field Age must be between {0.1} exclusive and {122.9} exclusive.");
356+
error.Source.Should().NotBeNull();
357+
error.Source.Pointer.Should().Be("/data/attributes/age");
333358
}
334359

335360
[Fact]
@@ -358,14 +383,17 @@ public async Task Cannot_use_relative_url()
358383
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
359384

360385
// Assert
361-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
362-
response.Errors.Should().HaveCount(1);
363-
364-
ErrorObject errorObject = response.Errors.First();
365-
errorObject.Title.Should().Be("Input validation failed.");
366-
errorObject.Detail.Should().Be("The BackgroundPicture field is not a valid fully-qualified http, https, or ftp URL.");
367-
errorObject.Source.Should().NotBeNull();
368-
errorObject.Source.Pointer.Should().Be("/data/attributes/backgroundPicture");
386+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
387+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
388+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
389+
exception.Errors.Should().HaveCount(1);
390+
391+
ErrorObject error = exception.Errors[0];
392+
error.Status.Should().Be("422");
393+
error.Title.Should().Be("Input validation failed.");
394+
error.Detail.Should().Be("The BackgroundPicture field is not a valid fully-qualified http, https, or ftp URL.");
395+
error.Source.Should().NotBeNull();
396+
error.Source.Pointer.Should().Be("/data/attributes/backgroundPicture");
369397
}
370398

371399
[Theory]
@@ -396,14 +424,17 @@ public async Task Cannot_exceed_collection_length_constraint(int length)
396424
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
397425

398426
// Assert
399-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
400-
response.Errors.Should().HaveCount(1);
401-
402-
ErrorObject errorObject = response.Errors.First();
403-
errorObject.Title.Should().Be("Input validation failed.");
404-
errorObject.Detail.Should().Be("The field Tags must be a string or collection type with a minimum length of '1' and maximum length of '10'.");
405-
errorObject.Source.Should().NotBeNull();
406-
errorObject.Source.Pointer.Should().Be("/data/attributes/tags");
427+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
428+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
429+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
430+
exception.Errors.Should().HaveCount(1);
431+
432+
ErrorObject error = exception.Errors[0];
433+
error.Status.Should().Be("422");
434+
error.Title.Should().Be("Input validation failed.");
435+
error.Detail.Should().Be("The field Tags must be a string or collection type with a minimum length of '1' and maximum length of '10'.");
436+
error.Source.Should().NotBeNull();
437+
error.Source.Pointer.Should().Be("/data/attributes/tags");
407438
}
408439

409440
[Fact]
@@ -432,14 +463,17 @@ public async Task Cannot_use_non_allowed_value()
432463
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
433464

434465
// Assert
435-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
436-
response.Errors.Should().HaveCount(1);
437-
438-
ErrorObject errorObject = response.Errors.First();
439-
errorObject.Title.Should().Be("Input validation failed.");
440-
errorObject.Detail.Should().Be("The CountryCode field does not equal any of the values specified in AllowedValuesAttribute.");
441-
errorObject.Source.Should().NotBeNull();
442-
errorObject.Source.Pointer.Should().Be("/data/attributes/countryCode");
466+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
467+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
468+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
469+
exception.Errors.Should().HaveCount(1);
470+
471+
ErrorObject error = exception.Errors[0];
472+
error.Status.Should().Be("422");
473+
error.Title.Should().Be("Input validation failed.");
474+
error.Detail.Should().Be("The CountryCode field does not equal any of the values specified in AllowedValuesAttribute.");
475+
error.Source.Should().NotBeNull();
476+
error.Source.Pointer.Should().Be("/data/attributes/countryCode");
443477
}
444478

445479
[Fact]
@@ -468,14 +502,17 @@ public async Task Cannot_use_denied_value()
468502
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
469503

470504
// Assert
471-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
472-
response.Errors.Should().HaveCount(1);
473-
474-
ErrorObject errorObject = response.Errors.First();
475-
errorObject.Title.Should().Be("Input validation failed.");
476-
errorObject.Detail.Should().Be("The Planet field equals one of the values specified in DeniedValuesAttribute.");
477-
errorObject.Source.Should().NotBeNull();
478-
errorObject.Source.Pointer.Should().Be("/data/attributes/planet");
505+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
506+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
507+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
508+
exception.Errors.Should().HaveCount(1);
509+
510+
ErrorObject error = exception.Errors[0];
511+
error.Status.Should().Be("422");
512+
error.Title.Should().Be("Input validation failed.");
513+
error.Detail.Should().Be("The Planet field equals one of the values specified in DeniedValuesAttribute.");
514+
error.Source.Should().NotBeNull();
515+
error.Source.Pointer.Should().Be("/data/attributes/planet");
479516
}
480517

481518
[Fact]
@@ -504,14 +541,17 @@ public async Task Cannot_use_TimeSpan_outside_of_valid_range()
504541
Func<Task> action = () => apiClient.SocialMediaAccounts.PostAsync(requestBody);
505542

506543
// Assert
507-
ErrorResponseDocument response = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
508-
response.Errors.Should().HaveCount(1);
509-
510-
ErrorObject errorObject = response.Errors.First();
511-
errorObject.Title.Should().Be("Input validation failed.");
512-
errorObject.Detail.Should().Be("The field NextRevalidation must be between 01:00:00 and 05:00:00.");
513-
errorObject.Source.Should().NotBeNull();
514-
errorObject.Source.Pointer.Should().Be("/data/attributes/nextRevalidation");
544+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
545+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
546+
exception.Message.Should().Be($"Exception of type '{typeof(ErrorResponseDocument).FullName}' was thrown.");
547+
exception.Errors.Should().HaveCount(1);
548+
549+
ErrorObject error = exception.Errors[0];
550+
error.Status.Should().Be("422");
551+
error.Title.Should().Be("Input validation failed.");
552+
error.Detail.Should().Be("The field NextRevalidation must be between 01:00:00 and 05:00:00.");
553+
error.Source.Should().NotBeNull();
554+
error.Source.Pointer.Should().Be("/data/attributes/nextRevalidation");
515555
}
516556

517557
[Fact]

0 commit comments

Comments
 (0)