Functional Testing For .NET Core API
Functional Testing For .NET Core API
Andrew Kulta
200 Followers About Follow
You have 2 free member-only stories left this month. Sign up for Medium and get an extra one
Functional testing is next level above the unit tests and gives us confidence that code
which we wrote works as it intended to. If we talking about functional testing in scope
of asp.net we mean a way how we test our API.
In scope of API we need to prepare possible requests which we expect to get and be
sure that
In test purposes out controller contains only single action to create some entity. it
Get started Open in app
could be any entity which required by our business rules. Besides we should
remember about authentication nowadays all APIs are protected by some kind of
authentication. Let`s assume that current API requires Authorization header with
Bearer token.
1 [ApiController]
2 public class MyController : ControllerBase
3 {
4 private readonly IService _service;
5
6 public MyController(IService service)
7 {
8 _service = service;
9 }
10
11 [HttpPost("entities")]
12 [ProducesResponseType(typeof(CreateResponse), (int)HttpStatusCode.OK)]
13 [ProducesResponseType(typeof(ExceptionResponse), (int)HttpStatusCode.BadRequest)]
14 public Task<CreateResponse> CreateAsync([FromBody] CreateRequest request)
15 {
16 return _service.CreateAsync(request);
17 }
18 }
ApiController.cs
hosted with ❤ by GitHub view raw
1 [TestFixture]
2 public class ApiControllerTests
3 {
4 private const string CreateUrl = "/entities";
5
https://medium.com/@kylia669/functional-testing-for-asp-net-core-api-4318df89311a 2/6
22/12/21 22:40 Functional testing for ASP.NET Core API | by Andrew Kulta | Medium
54 PropertyName = "propertyValue"
Get
55
started };Open in app
56 var json = JsonConvert.SerializeObject(request);
57 using var data = new StringContent(json, Encoding.UTF8, "application/json");
58
59 // Act
60 var response = await _client?.PostAsync(CreateUrl, data)!;
61
62 // Assert
63 response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
64 }
65
66 [Test]
67 public async Task CreateAsync_Should_Return400_When_RequestValidationFailed()
68 {
69 // Arrange
70 var request = new CreateRequest();
71 var json = JsonConvert.SerializeObject(request);
72 using var data = new StringContent(json, Encoding.UTF8, "application/json");
73 var token = await _tokenBuilder.BuildJWTToken();
74 _client?.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
75
76 // Act
77 var response = await _client?.PostAsync(CreateUrl, data)!;
78
79 // Assert
80 response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
81 }
82
83 [Test]
84 public async Task CreateAsync_Should_ReturnCreateResponse()
85 {
86 // Arrange
87 var request = new CreateRequest
88 {
89 PropertyName = "propertyValue"
90 };
91 var json = JsonConvert.SerializeObject(request);
92 using var data = new StringContent(json, Encoding.UTF8, "application/json");
93 var token = await _tokenBuilder.BuildJWTToken();
94 _client?.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
95
96 var expected = new CreateResponse
97 {
98 PropertyName = "propertyValue"
99 };
100
101 // Act
https://medium.com/@kylia669/functional-testing-for-asp-net-core-api-4318df89311a 4/6
22/12/21 22:40 Functional testing for ASP.NET Core API | by Andrew Kulta | Medium
101 // Act
102 var response = await _client?.PostAsync(CreateUrl, data)!;
Get started Open in app
103
104 // Assert
105 response.StatusCode.Should().Be(HttpStatusCode.OK);
106 var responseBody = await response.Content.ReadAsStringAsync();
107 var responseObject = JsonConvert.DeserializeObject<CreateResponse>(responseBody);
108 responseObject.Should().BeEquivalentTo(expected);
109 }
110 }
We should cover that API endpoint protected by authentication and clients can`t
request it without proper token. In order to do this we need to prepare test server
with proper authentication setup. To do it in setup we need to override
JwtBearerOptions with our test authentication which relies on auth token signed by
SymmetricSecurityKey. To be compliant with security rules we should avoid to store
any secrets in code and I don`t suggest you to violate this rule even for test project.
23 TestConstants.Audience,
Get started
24 Open in appjwtValidity,
expires:
25 signingCredentials: creds,
26 claims: new List<Claim>
27 {
28 new (ClaimTypes.Role, "owner"),
29 });
30
31 return new JwtSecurityTokenHandler().WriteToken(token);
32 }
33 }
TokenBuilder.cs
hosted with ❤ by GitHub view raw
In conclusion I hope you get feeling that functional tests are quite simple and it allows
to verify you API each time when something changed. Functional tests could be
included as a step in your build pipeline. It gives to even to confidence that
everything works good before deploying to production.
https://medium.com/@kylia669/functional-testing-for-asp-net-core-api-4318df89311a 6/6