Skip to content

Commit 73b897c

Browse files
Add NSwag client test
Add a test that uses an NSwag-generated client.
1 parent d413d8f commit 73b897c

7 files changed

Lines changed: 2754 additions & 11 deletions

File tree

.config/dotnet-tools.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
"kiota"
3030
],
3131
"rollForward": false
32+
},
33+
"nswag.consolecore": {
34+
"version": "14.6.3",
35+
"commands": [
36+
"nswag"
37+
],
38+
"rollForward": false
3239
}
3340
}
3441
}

test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ await VerifyDirectory(
9191
options: new() { RecurseSubdirectories = true }).UseDirectory("snapshots");
9292
}
9393

94+
[Fact]
95+
public async Task VerifyNSwagTodoAppClient()
96+
{
97+
await VerifyDirectory(
98+
Path.Combine(GetProjectRoot(), "NSwagTodoClient"),
99+
pattern: "*.cs",
100+
options: new() { RecurseSubdirectories = true }).UseDirectory("snapshots");
101+
}
102+
94103
private static string GetProjectRoot() =>
95104
typeof(CodeGenerationTests).Assembly
96105
.GetCustomAttributes<AssemblyMetadataAttribute>()

test/Swashbuckle.AspNetCore.IntegrationTests/KiotaClientTests.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ await WithTodoAppClientAsync(async (client) =>
2525
Assert.NotNull(items);
2626
Assert.NotNull(items.Items);
2727

28-
var beforeCount = items.Items.Count;
29-
3028
// Arrange
3129
var text = "Buy eggs";
3230

@@ -87,10 +85,9 @@ await client.Api.Items[new(itemId)].Priority.PatchAsync(
8785
// Assert - The item was completed
8886
Assert.NotNull(items);
8987
Assert.NotNull(items.Items);
90-
Assert.Equal(beforeCount + 1, items.Items.Count);
9188
Assert.Contains(items.Items, (x) => x.Id == itemId);
9289

93-
item = items.Items.Last();
90+
item = items.Items.Single((p) => p.Id == itemId);
9491

9592
Assert.NotNull(item);
9693
Assert.Equal(itemId, item.Id);
@@ -107,7 +104,6 @@ await client.Api.Items[new(itemId)].Priority.PatchAsync(
107104

108105
Assert.NotNull(items);
109106
Assert.NotNull(items.Items);
110-
Assert.Equal(beforeCount, items.Items.Count);
111107
Assert.DoesNotContain(items.Items, (x) => x.Id == itemId);
112108

113109
// Act
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#if NET10_0_OR_GREATER
2+
3+
using Microsoft.AspNetCore.Http;
4+
using TodoApp.NSwagClient;
5+
6+
namespace Swashbuckle.AspNetCore.IntegrationTests;
7+
8+
public class NSwagClientTests
9+
{
10+
[Fact]
11+
public async Task Can_Manage_Todo_Items_With_Api()
12+
{
13+
// Arrange
14+
await WithTodoAppClientAsync(async (client) =>
15+
{
16+
var cancellationToken = TestContext.Current.CancellationToken;
17+
18+
// Act - Get all the items
19+
var items = await client.ListTodosAsync(cancellationToken);
20+
21+
// Assert
22+
Assert.NotNull(items);
23+
Assert.NotNull(items.Items);
24+
25+
// Arrange
26+
var text = "Buy eggs";
27+
28+
// Act - Add a new item
29+
var createdItem = await client.CreateTodoAsync(
30+
new() { Text = text },
31+
cancellationToken);
32+
33+
// Assert - An item was created
34+
Assert.NotNull(createdItem);
35+
Assert.NotEqual(default, createdItem.Id);
36+
37+
// Arrange - Get the new item's URL and Id
38+
var itemId = createdItem.Id;
39+
40+
// Act - Get the item
41+
var item = await client.GetTodoAsync(new(itemId), cancellationToken);
42+
43+
// Assert - Verify the item was created correctly
44+
Assert.NotNull(item);
45+
Assert.Equal(itemId, item.Id);
46+
Assert.Null(item.CompletedAt);
47+
Assert.NotEqual(default, item.CreatedAt);
48+
Assert.Equal(item.CreatedAt, item.LastUpdated);
49+
Assert.Equal(TodoPriority.Normal, item.Priority);
50+
Assert.Equal(text, item.Text);
51+
52+
// Act - Update the item to be high priority
53+
await client.UpdateTodoPriorityAsync(
54+
new(itemId),
55+
new() { Priority = TodoPriority.High },
56+
cancellationToken);
57+
58+
item = await client.GetTodoAsync(new(itemId), cancellationToken);
59+
60+
Assert.NotNull(item);
61+
Assert.Equal(itemId, item.Id);
62+
Assert.Null(item.CompletedAt);
63+
Assert.NotEqual(default, item.CreatedAt);
64+
Assert.Equal(item.CreatedAt, item.LastUpdated);
65+
Assert.Equal(TodoPriority.High, item.Priority);
66+
Assert.Equal(text, item.Text);
67+
68+
// Act - Mark the item as being completed
69+
await client.CompleteTodoAsync(new(itemId), cancellationToken);
70+
71+
item = await client.GetTodoAsync(new(itemId), cancellationToken);
72+
73+
Assert.NotNull(item);
74+
Assert.Equal(itemId, item.Id);
75+
Assert.Equal(text, item.Text);
76+
Assert.NotNull(item.CompletedAt);
77+
Assert.Equal(item.CompletedAt.Value, item.LastUpdated);
78+
Assert.True(item.CompletedAt.Value > item.CreatedAt);
79+
80+
// Act - Get all the items
81+
items = await client.ListTodosAsync(cancellationToken);
82+
83+
// Assert - The item was completed
84+
Assert.NotNull(items);
85+
Assert.NotNull(items.Items);
86+
Assert.Contains(items.Items, (x) => x.Id == itemId);
87+
88+
item = items.Items.Single((p) => p.Id == itemId);
89+
90+
Assert.NotNull(item);
91+
Assert.Equal(itemId, item.Id);
92+
Assert.Equal(text, item.Text);
93+
Assert.NotNull(item.CompletedAt);
94+
Assert.Equal(item.CompletedAt.Value, item.LastUpdated);
95+
Assert.True(item.CompletedAt.Value > item.CreatedAt);
96+
97+
// Act - Delete the item
98+
await client.DeleteTodoAsync(new(itemId), cancellationToken);
99+
100+
// Assert - The item no longer exists
101+
items = await client.ListTodosAsync(cancellationToken);
102+
103+
Assert.NotNull(items);
104+
Assert.NotNull(items.Items);
105+
Assert.DoesNotContain(items.Items, (x) => x.Id == itemId);
106+
107+
// Act
108+
var error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
109+
() => client.GetTodoAsync(new(itemId), cancellationToken));
110+
111+
var problem = error.Result;
112+
113+
// Assert
114+
Assert.NotNull(problem);
115+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
116+
Assert.Equal("Not Found", problem.Title);
117+
Assert.Equal("Item not found.", problem.Detail);
118+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
119+
Assert.Null(problem.Instance);
120+
121+
// Act
122+
error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
123+
() => client.CompleteTodoAsync(new(itemId), cancellationToken));
124+
125+
problem = error.Result;
126+
127+
// Assert
128+
Assert.NotNull(problem);
129+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
130+
Assert.Equal("Not Found", problem.Title);
131+
Assert.Equal("Item not found.", problem.Detail);
132+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
133+
Assert.Null(problem.Instance);
134+
135+
// Act
136+
error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
137+
() => client.UpdateTodoPriorityAsync(new(itemId), new() { Priority = TodoPriority.Low }, cancellationToken));
138+
139+
problem = error.Result;
140+
141+
// Assert
142+
Assert.NotNull(problem);
143+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
144+
Assert.Equal("Not Found", problem.Title);
145+
Assert.Equal("Item not found.", problem.Detail);
146+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
147+
Assert.Null(problem.Instance);
148+
});
149+
}
150+
151+
[Fact]
152+
public async Task Cannot_Create_Todo_Item_With_No_Text()
153+
{
154+
// Arrange
155+
await WithTodoAppClientAsync(async (client) =>
156+
{
157+
var cancellationToken = TestContext.Current.CancellationToken;
158+
159+
// Act
160+
var error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
161+
() => client.CreateTodoAsync(new() { Text = string.Empty }, cancellationToken));
162+
163+
var problem = error.Result;
164+
165+
// Assert
166+
Assert.NotNull(problem);
167+
Assert.Equal(StatusCodes.Status400BadRequest, problem.Status);
168+
Assert.Equal("Bad Request", problem.Title);
169+
Assert.Equal("No item text specified.", problem.Detail);
170+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.1", problem.Type);
171+
Assert.Null(problem.Instance);
172+
});
173+
}
174+
175+
[Fact]
176+
public async Task Cannot_Complete_Todo_Item_Multiple_Times()
177+
{
178+
// Arrange
179+
await WithTodoAppClientAsync(async (client) =>
180+
{
181+
var cancellationToken = TestContext.Current.CancellationToken;
182+
183+
var createdItem = await client.CreateTodoAsync(
184+
new() { Text = "Something" },
185+
cancellationToken);
186+
187+
await client.CompleteTodoAsync(new(createdItem.Id), cancellationToken);
188+
189+
// Act
190+
var error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
191+
() => client.CompleteTodoAsync(new(createdItem.Id), cancellationToken));
192+
193+
var problem = error.Result;
194+
195+
// Assert
196+
Assert.NotNull(problem);
197+
Assert.Equal(StatusCodes.Status400BadRequest, problem.Status);
198+
Assert.Equal("Bad Request", problem.Title);
199+
Assert.Equal("Item already completed.", problem.Detail);
200+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.1", problem.Type);
201+
Assert.Null(problem.Instance);
202+
});
203+
}
204+
205+
[Fact]
206+
public async Task Cannot_Complete_Deleted_Todo_Item()
207+
{
208+
// Arrange
209+
await WithTodoAppClientAsync(async (client) =>
210+
{
211+
var cancellationToken = TestContext.Current.CancellationToken;
212+
213+
var createdItem = await client.CreateTodoAsync(
214+
new() { Text = "Something" },
215+
cancellationToken);
216+
217+
await client.DeleteTodoAsync(new(createdItem.Id), cancellationToken);
218+
219+
// Act
220+
var error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
221+
() => client.CompleteTodoAsync(new(createdItem.Id), cancellationToken));
222+
223+
var problem = error.Result;
224+
225+
// Assert
226+
Assert.NotNull(problem);
227+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
228+
Assert.Equal("Not Found", problem.Title);
229+
Assert.Equal("Item not found.", problem.Detail);
230+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
231+
Assert.Null(problem.Instance);
232+
});
233+
}
234+
235+
[Fact]
236+
public async Task Cannot_Delete_Todo_Item_Multiple_Times()
237+
{
238+
// Arrange
239+
await WithTodoAppClientAsync(async (client) =>
240+
{
241+
var cancellationToken = TestContext.Current.CancellationToken;
242+
243+
var createdItem = await client.CreateTodoAsync(
244+
new() { Text = "Something" },
245+
cancellationToken);
246+
247+
await client.DeleteTodoAsync(new(createdItem.Id), cancellationToken);
248+
249+
// Act
250+
var error = await Assert.ThrowsAsync<ApiException<ProblemDetails>>(
251+
() => client.DeleteTodoAsync(new(createdItem.Id), cancellationToken));
252+
253+
var problem = error.Result;
254+
255+
// Assert
256+
Assert.NotNull(problem);
257+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
258+
Assert.Equal("Not Found", problem.Title);
259+
Assert.Equal("Item not found.", problem.Detail);
260+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
261+
Assert.Null(problem.Instance);
262+
});
263+
}
264+
265+
private static async Task WithTodoAppClientAsync(Func<NSwagTodoApiClient, Task> callback)
266+
{
267+
using var httpClient = SwaggerIntegrationTests.GetHttpClientForTestApplication(typeof(TodoApp.Program));
268+
269+
var client = new NSwagTodoApiClient(httpClient.BaseAddress.ToString(), httpClient);
270+
271+
await callback(client);
272+
}
273+
}
274+
275+
#endif

0 commit comments

Comments
 (0)