【问题标题】:testability considerations while creating controllers创建控制器时的可测试性注意事项
【发布时间】:2017-06-05 00:25:40
【问题描述】:

我在 Web API 2 中编写控制器,将对其执行 odata 查询:

[Route("", Name = "GetAccount")]
[HttpGet]
public async Task<IHttpActionResult> GetAccount()
{
    var query = Request.RequestUri.PathAndQuery.Split('/')[2]; //this query variable will be something "filter=name eq 'alex'"
    var response = _accountService.Get(query);

    if (!response.Result.IsSuccessStatusCode)
    {
        return NotFound();
    }

    var readAsAsync = response.Result.Content.ReadAsAsync<object>();
    if (readAsAsync == null)
    {
        return NotFound();
    }

    var result = await readAsAsync;
    return Ok(result);
} 

如何注入Request,特别是与var query = Request.RequestUri.PathAndQuery.Split('/')[2]; 相关的内容?

这是我为此控制器编写的一个非常基本的测试:

[TestMethod]
public void GetAccount_Returns_IHttpActionResultTask()
{
    var accountsService = new Mock<IAccountService>();
    var sut = new AccountsController(accountsService.Object);

    Assert.IsInstanceOfType(sut.GetAccount(), typeof(Task<IHttpActionResult>));
}

为了使用 Request.RequestUri.... 的不同值进行测试,我该如何重写我的控制器以提高可测试性?

【问题讨论】:

  • 可以在 apicontroller 上设置 Request 属性。
  • 谢谢。你能举个例子或指出一个资源吗?
  • 注意到被测方法存在一些潜在问题,其中混合了异步调用和阻塞调用,例如.Result

标签: c# asp.net unit-testing asp.net-web-api


【解决方案1】:

ApiCntroller 上设置Request 属性。

[TestMethod]
public async Task GetAccount_Returns_IHttpActionResult() {
    //Arrange
    var accountsService = new Mock<IAccountService>();
    var sut = new AccountsController(accountsService.Object);
    sut.Request = new HttpRequestMessage {
        RequestUri = new Uri("http://localhost/api/accounts?filter=name")
    };

    //Act
    var result = await sut.GetAccount();

    //Assert
    Assert.IsInstanceOfType(result, typeof(IHttpActionResult));
}

被测方法也存在或一些潜在的阻塞问题。将 async/await 与 .Result 阻塞调用混合会导致死锁。

重构:

[Route("", Name = "GetAccount")]
[HttpGet]
public async Task<IHttpActionResult> GetAccount() {
    var query = Request.RequestUri.PathAndQuery.Split('/')[2]; //this query variable will be something "filter=name eq 'alex'"
    var response = await _accountService.Get(query);

    if (!response.IsSuccessStatusCode) {
        return NotFound();
    }

    var readAsAsync = response.Content.ReadAsAsync<object>();
    if (readAsAsync == null) {
        return NotFound();
    }

    var result = await readAsAsync;
    return Ok(result);
}

【讨论】:

    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    相关资源
    最近更新 更多