Home > Net >  How to write unit tests around properties with the FromRoute attribute in C#
How to write unit tests around properties with the FromRoute attribute in C#

Time:09-21

I have a controller that I'm writing for a .NET 5.0 project:

/// <summary>
/// A controller that handles requests related to participants
/// </summary>
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/rooms/{RoomId}/participants")]
[ApiController]
[Authorize("ClientIdPolicy")]
public sealed class ParticipantController : ControllerBase {

    // The room ID that should be present on every route
    [FromRoute]
    private string RoomId { get; set; }

    [HttpPost]
    [ResponseType(typeof(DTO.Room))]
    public async Task<IActionResult> PostAsync(DTO.Participant participant,
        CancellationToken token = default) {
        if (string.IsNullOrWhitespace(RoomId)) {
            return BadRequest(new ArgumentException("Room ID was empty"));
        }

        // Other controller code
    }
}

Now, I'm trying to write unit tests around it:

var controller = new ParticipantController() {
    ControllerContext = new ControllerContext(new ActionContext(
    HttpUtilities.TestHttpContext("/v1.0/rooms/a8e3e87d-21e9-4a23-92cc-a50a662c1556/participants"),
        new RouteData(), new ControllerActionDescriptor()))
};

IActionResult result = await controller.PostAsync(participant, Source.Token).ConfigureAwait(false);

The problem I'm having is that, when I call into the controller, RoomId is null. How do I ensure that this value is created properly so I can test?

CodePudding user response:

Didn't know you could use the attributes this way. I would implement such a controller by providing the route as parameter of the function itself, making the testing much easier:

/// <summary>
/// A controller that handles requests related to participants
/// </summary>
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/rooms")]
[ApiController]
[Authorize("ClientIdPolicy")]
public sealed class ParticipantController : ControllerBase {

    [HttpPost("{RoomId}/participants")]
    [ResponseType(typeof(DTO.Room))]
    public async Task<IActionResult> PostAsync(DTO.Participant participant,
        [FromRoute] string RoomId,
        CancellationToken token = default) {
        if (string.IsNullOrWhitespace(RoomId)) {
            return BadRequest(new ArgumentException("Room ID was empty"));
        }

        // Other controller code
    }
}
  • Related