Skip to content

Commit ecc10ac

Browse files
committed
fix(controllers): ensure consistent return type in PostAsync method
1 parent 6a6d5a6 commit ecc10ac

File tree

5 files changed

+147
-95
lines changed

5 files changed

+147
-95
lines changed

Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/PlayerControllerTests.cs

Lines changed: 119 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ public async Task GivenPostAsync_WhenModelStateIsInvalid_ThenResponseStatusCodeS
3232
controller.ModelState.Merge(PlayerStubs.CreateModelError("SquadNumber", "Required"));
3333

3434
// Act
35-
var result = await controller.PostAsync(It.IsAny<PlayerRequestModel>()) as BadRequest;
35+
var result = await controller.PostAsync(It.IsAny<PlayerRequestModel>());
3636

3737
// Assert
38-
result.Should().NotBeNull().And.BeOfType<BadRequest>();
39-
result?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
38+
if (result is BadRequest response)
39+
{
40+
response.Should().NotBeNull().And.BeOfType<BadRequest>();
41+
response.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
42+
}
4043
}
4144

4245
[Fact]
@@ -45,53 +48,61 @@ public async Task GivenPostAsync_WhenServiceRetrieveByIdAsyncReturnsPlayer_ThenR
4548
{
4649
// Arrange
4750
var id = 10;
51+
var payload = PlayerFakes.CreateRequestModelForOneExistingById(id);
4852
var (service, logger) = PlayerMocks.InitControllerMocks();
4953
service
5054
.Setup(service => service.RetrieveByIdAsync(It.IsAny<long>()))
5155
.ReturnsAsync(PlayerFakes.CreateResponseModelForOneExistingById(id));
52-
var payload = PlayerFakes.CreateRequestModelForOneExistingById(id);
5356

5457
var controller = new PlayerController(service.Object, logger.Object);
5558

5659
// Act
57-
var result = await controller.PostAsync(payload) as Conflict;
60+
var result = await controller.PostAsync(payload);
5861

5962
// Assert
60-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
61-
result.Should().NotBeNull().And.BeOfType<Conflict>();
62-
result?.StatusCode.Should().Be(StatusCodes.Status409Conflict);
63+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
64+
service.Verify(service => service.CreateAsync(It.IsAny<PlayerRequestModel>()), Times.Never);
65+
if (result is Conflict response)
66+
{
67+
response.Should().NotBeNull().And.BeOfType<Conflict>();
68+
response.StatusCode.Should().Be(StatusCodes.Status409Conflict);
69+
}
6370
}
6471

6572
[Fact]
6673
[Trait("Category", "Unit")]
6774
public async Task GivenPostAsync_WhenServiceRetrieveByIdAsyncReturnsNull_ThenResponseStatusCodeShouldBe201Created()
6875
{
6976
// Arrange
70-
var request = PlayerFakes.CreateRequestModelForOneNew();
77+
var payload = PlayerFakes.CreateRequestModelForOneNew();
78+
var content = PlayerFakes.CreateResponseModelForOneNew();
7179
var (service, logger) = PlayerMocks.InitControllerMocks();
7280
service
7381
.Setup(service => service.RetrieveByIdAsync(It.IsAny<long>()))
7482
.ReturnsAsync(null as PlayerResponseModel);
75-
service.Setup(service => service.CreateAsync(It.IsAny<PlayerRequestModel>()));
83+
service
84+
.Setup(service => service.CreateAsync(It.IsAny<PlayerRequestModel>()))
85+
.ReturnsAsync(content);
7686

7787
var controller = new PlayerController(service.Object, logger.Object)
7888
{
7989
Url = PlayerMocks.SetupUrlHelperMock().Object,
8090
};
8191

8292
// Act
83-
var result = await controller.PostAsync(request) as Created<PlayerRequestModel>;
93+
var result = await controller.PostAsync(payload);
8494

8595
// Assert
86-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
87-
service.Verify(
88-
service => service.CreateAsync(It.IsAny<PlayerRequestModel>()),
89-
Times.Exactly(1)
90-
);
91-
result.Should().NotBeNull().And.BeOfType<Created<PlayerRequestModel>>();
92-
result?.StatusCode.Should().Be(StatusCodes.Status201Created);
93-
result?.Value.Should().BeEquivalentTo(request); // Request not mapped to Response
94-
result?.Location.Should().Be($"/players/{request.Id}");
96+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
97+
service.Verify(service => service.CreateAsync(It.IsAny<PlayerRequestModel>()), Times.Once);
98+
if (result is CreatedAtRoute<PlayerRequestModel> response)
99+
{
100+
response.Should().NotBeNull().And.BeOfType<Created<PlayerResponseModel>>();
101+
response.StatusCode.Should().Be(StatusCodes.Status201Created);
102+
response.Value.Should().BeEquivalentTo(content);
103+
response.RouteName.Should().Be("GetById");
104+
response.RouteValues.Should().NotBeNull().And.ContainKey("id");
105+
}
95106
}
96107

97108
/* -------------------------------------------------------------------------
@@ -110,14 +121,17 @@ public async Task GivenGetAsync_WhenServiceRetrieveAsyncReturnsListOfPlayers_The
110121
var controller = new PlayerController(service.Object, logger.Object);
111122

112123
// Act
113-
var result = await controller.GetAsync() as Ok<List<PlayerResponseModel>>;
124+
var result = await controller.GetAsync();
114125

115126
// Assert
116-
service.Verify(service => service.RetrieveAsync(), Times.Exactly(1));
117-
result.Should().NotBeNull().And.BeOfType<Ok<List<PlayerResponseModel>>>();
118-
result?.StatusCode.Should().Be(StatusCodes.Status200OK);
119-
result?.Value.Should().NotBeNull().And.BeOfType<List<PlayerResponseModel>>();
120-
result?.Value.Should().BeEquivalentTo(players);
127+
service.Verify(service => service.RetrieveAsync(), Times.Once);
128+
if (result is Ok<List<PlayerResponseModel>> response)
129+
{
130+
response.Should().NotBeNull().And.BeOfType<Ok<List<PlayerResponseModel>>>();
131+
response.StatusCode.Should().Be(StatusCodes.Status200OK);
132+
response.Value.Should().NotBeNull().And.BeOfType<List<PlayerResponseModel>>();
133+
response.Value.Should().BeEquivalentTo(players);
134+
}
121135
}
122136

123137
[Fact]
@@ -131,12 +145,15 @@ public async Task GivenGetAsync_WhenServiceRetrieveAsyncReturnsEmptyList_ThenRes
131145
var controller = new PlayerController(service.Object, logger.Object);
132146

133147
// Act
134-
var result = await controller.GetAsync() as NotFound;
148+
var result = await controller.GetAsync();
135149

136150
// Assert
137-
service.Verify(service => service.RetrieveAsync(), Times.Exactly(1));
138-
result.Should().NotBeNull().And.BeOfType<NotFound>();
139-
result?.StatusCode.Should().Be(StatusCodes.Status404NotFound);
151+
service.Verify(service => service.RetrieveAsync(), Times.Once);
152+
if (result is NotFound response)
153+
{
154+
response.Should().NotBeNull().And.BeOfType<NotFound>();
155+
response.StatusCode.Should().Be(StatusCodes.Status404NotFound);
156+
}
140157
}
141158

142159
[Fact]
@@ -152,12 +169,15 @@ public async Task GivenGetByIdAsync_WhenServiceRetrieveByIdAsyncReturnsNull_Then
152169
var controller = new PlayerController(service.Object, logger.Object);
153170

154171
// Act
155-
var result = await controller.GetByIdAsync(It.IsAny<long>()) as NotFound;
172+
var result = await controller.GetByIdAsync(It.IsAny<long>());
156173

157174
// Assert
158-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
159-
result.Should().NotBeNull().And.BeOfType<NotFound>();
160-
result?.StatusCode.Should().Be(StatusCodes.Status404NotFound);
175+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
176+
if (result is NotFound response)
177+
{
178+
response.Should().NotBeNull().And.BeOfType<NotFound>();
179+
response.StatusCode.Should().Be(StatusCodes.Status404NotFound);
180+
}
161181
}
162182

163183
[Fact]
@@ -172,14 +192,17 @@ public async Task GivenGetByIdAsync_WhenServiceRetrieveByIdAsyncReturnsPlayer_Th
172192
var controller = new PlayerController(service.Object, logger.Object);
173193

174194
// Act
175-
var result = await controller.GetByIdAsync(It.IsAny<long>()) as Ok<PlayerResponseModel>;
195+
var result = await controller.GetByIdAsync(It.IsAny<long>());
176196

177197
// Assert
178-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
179-
result.Should().NotBeNull().And.BeOfType<Ok<PlayerResponseModel>>();
180-
result?.StatusCode.Should().Be(StatusCodes.Status200OK);
181-
result?.Value.Should().NotBeNull().And.BeOfType<PlayerResponseModel>();
182-
result?.Value.Should().BeEquivalentTo(player);
198+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
199+
if (result is Ok<PlayerResponseModel> response)
200+
{
201+
response.Should().NotBeNull().And.BeOfType<Ok<PlayerResponseModel>>();
202+
response.StatusCode.Should().Be(StatusCodes.Status200OK);
203+
response.Value.Should().NotBeNull().And.BeOfType<PlayerResponseModel>();
204+
response.Value.Should().BeEquivalentTo(player);
205+
}
183206
}
184207

185208
[Fact]
@@ -195,15 +218,15 @@ public async Task GivenGetBySquadNumberAsync_WhenServiceRetrieveBySquadNumberAsy
195218
var controller = new PlayerController(service.Object, logger.Object);
196219

197220
// Act
198-
var result = await controller.GetBySquadNumberAsync(It.IsAny<int>()) as NotFound;
221+
var result = await controller.GetBySquadNumberAsync(It.IsAny<int>());
199222

200223
// Assert
201-
service.Verify(
202-
service => service.RetrieveBySquadNumberAsync(It.IsAny<int>()),
203-
Times.Exactly(1)
204-
);
205-
result.Should().NotBeNull().And.BeOfType<NotFound>();
206-
result?.StatusCode.Should().Be(StatusCodes.Status404NotFound);
224+
service.Verify(service => service.RetrieveBySquadNumberAsync(It.IsAny<int>()), Times.Once);
225+
if (result is NotFound response)
226+
{
227+
response.Should().NotBeNull().And.BeOfType<NotFound>();
228+
response.StatusCode.Should().Be(StatusCodes.Status404NotFound);
229+
}
207230
}
208231

209232
[Fact]
@@ -220,18 +243,17 @@ public async Task GivenGetBySquadNumberAsync_WhenServiceRetrieveBySquadNumberAsy
220243
var controller = new PlayerController(service.Object, logger.Object);
221244

222245
// Act
223-
var result =
224-
await controller.GetBySquadNumberAsync(It.IsAny<int>()) as Ok<PlayerResponseModel>;
246+
var result = await controller.GetBySquadNumberAsync(It.IsAny<int>());
225247

226248
// Assert
227-
service.Verify(
228-
service => service.RetrieveBySquadNumberAsync(It.IsAny<int>()),
229-
Times.Exactly(1)
230-
);
231-
result.Should().NotBeNull().And.BeOfType<Ok<PlayerResponseModel>>();
232-
result?.StatusCode.Should().Be(StatusCodes.Status200OK);
233-
result?.Value.Should().NotBeNull().And.BeOfType<PlayerResponseModel>();
234-
result?.Value.Should().BeEquivalentTo(player);
249+
service.Verify(service => service.RetrieveBySquadNumberAsync(It.IsAny<int>()), Times.Once);
250+
if (result is Ok<PlayerResponseModel> response)
251+
{
252+
response.Should().NotBeNull().And.BeOfType<Ok<PlayerResponseModel>>();
253+
response.StatusCode.Should().Be(StatusCodes.Status200OK);
254+
response.Value.Should().NotBeNull().And.BeOfType<PlayerResponseModel>();
255+
response.Value.Should().BeEquivalentTo(player);
256+
}
235257
}
236258

237259
/* -------------------------------------------------------------------------
@@ -249,13 +271,16 @@ public async Task GivenPutAsync_WhenModelStateIsInvalid_ThenResponseStatusCodeSh
249271
controller.ModelState.Merge(PlayerStubs.CreateModelError("SquadNumber", "Required"));
250272

251273
// Act
252-
var result =
253-
await controller.PutAsync(It.IsAny<long>(), It.IsAny<PlayerRequestModel>())
254-
as BadRequest;
274+
var result = await controller.PutAsync(It.IsAny<long>(), It.IsAny<PlayerRequestModel>());
255275

256276
// Assert
257-
result.Should().NotBeNull().And.BeOfType<BadRequest>();
258-
result?.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
277+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Never);
278+
service.Verify(service => service.UpdateAsync(It.IsAny<PlayerRequestModel>()), Times.Never);
279+
if (result is BadRequest response)
280+
{
281+
response.Should().NotBeNull().And.BeOfType<BadRequest>();
282+
response.StatusCode.Should().Be(StatusCodes.Status400BadRequest);
283+
}
259284
}
260285

261286
[Fact]
@@ -271,13 +296,16 @@ public async Task GivenPutAsync_WhenServiceRetrieveByIdAsyncReturnsNull_ThenResp
271296
var controller = new PlayerController(service.Object, logger.Object);
272297

273298
// Act
274-
var result =
275-
await controller.PutAsync(It.IsAny<long>(), It.IsAny<PlayerRequestModel>()) as NotFound;
299+
var result = await controller.PutAsync(It.IsAny<long>(), It.IsAny<PlayerRequestModel>());
276300

277301
// Assert
278-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
279-
result.Should().NotBeNull().And.BeOfType<NotFound>();
280-
result?.StatusCode.Should().Be(StatusCodes.Status404NotFound);
302+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
303+
service.Verify(service => service.UpdateAsync(It.IsAny<PlayerRequestModel>()), Times.Never);
304+
if (result is NotFound response)
305+
{
306+
response.Should().NotBeNull().And.BeOfType<NotFound>();
307+
response.StatusCode.Should().Be(StatusCodes.Status404NotFound);
308+
}
281309
}
282310

283311
[Fact]
@@ -296,16 +324,16 @@ public async Task GivenPutAsync_WhenServiceRetrieveByIdAsyncReturnsPlayer_ThenRe
296324
var controller = new PlayerController(service.Object, logger.Object);
297325

298326
// Act
299-
var result = await controller.PutAsync(id, player) as NoContent;
327+
var result = await controller.PutAsync(id, player);
300328

301329
// Assert
302-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
303-
service.Verify(
304-
service => service.UpdateAsync(It.IsAny<PlayerRequestModel>()),
305-
Times.Exactly(1)
306-
);
307-
result.Should().NotBeNull().And.BeOfType<NoContent>();
308-
result?.StatusCode.Should().Be(StatusCodes.Status204NoContent);
330+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
331+
service.Verify(service => service.UpdateAsync(It.IsAny<PlayerRequestModel>()), Times.Once);
332+
if (result is NoContent response)
333+
{
334+
response.Should().NotBeNull().And.BeOfType<NoContent>();
335+
response.StatusCode.Should().Be(StatusCodes.Status204NoContent);
336+
}
309337
}
310338

311339
/* -------------------------------------------------------------------------
@@ -325,12 +353,16 @@ public async Task GivenDeleteAsync_WhenServiceRetrieveByIdAsyncReturnsNull_ThenR
325353
var controller = new PlayerController(service.Object, logger.Object);
326354

327355
// Act
328-
var result = await controller.DeleteAsync(It.IsAny<long>()) as NotFound;
356+
var result = await controller.DeleteAsync(It.IsAny<long>());
329357

330358
// Assert
331-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
332-
result.Should().NotBeNull().And.BeOfType<NotFound>();
333-
result?.StatusCode.Should().Be(StatusCodes.Status404NotFound);
359+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
360+
service.Verify(service => service.DeleteAsync(It.IsAny<long>()), Times.Never);
361+
if (result is NotFound response)
362+
{
363+
response.Should().NotBeNull().And.BeOfType<NotFound>();
364+
response.StatusCode.Should().Be(StatusCodes.Status404NotFound);
365+
}
334366
}
335367

336368
[Fact]
@@ -347,13 +379,16 @@ public async Task GivenDeleteAsync_WhenServiceRetrieveByIdAsyncReturnsPlayer_The
347379
var controller = new PlayerController(service.Object, logger.Object);
348380

349381
// Act
350-
var result = await controller.DeleteAsync(It.IsAny<long>()) as NoContent;
382+
var result = await controller.DeleteAsync(It.IsAny<long>());
351383

352384
// Assert
353-
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Exactly(1));
354-
service.Verify(service => service.DeleteAsync(It.IsAny<long>()), Times.Exactly(1));
355-
result.Should().NotBeNull().And.BeOfType<NoContent>();
356-
result?.StatusCode.Should().Be(StatusCodes.Status204NoContent);
385+
service.Verify(service => service.RetrieveByIdAsync(It.IsAny<long>()), Times.Once);
386+
service.Verify(service => service.DeleteAsync(It.IsAny<long>()), Times.Once);
387+
if (result is NoContent response)
388+
{
389+
response.Should().NotBeNull().And.BeOfType<NoContent>();
390+
response.StatusCode.Should().Be(StatusCodes.Status204NoContent);
391+
}
357392
}
358393

359394
protected virtual void Dispose(bool disposing)

0 commit comments

Comments
 (0)