如何在 C# 中使用 FromRoute 属性围绕属性编写单元测试

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

我有一个正在为 .NET 5.0 项目编写的控制器:

/// <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
    }
}

现在,我正在尝试围绕它编写单元测试:

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);

我遇到的问题是,当我调用控制器时,RoomId 为空。如何确保正确创建此值以便我进行测试?

不知道您可以这样使用属性。我将通过提供路由作为函数本身的参数来实现这样的控制器,从而使测试更加容易:

/// <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
    }
}