如何在返回IHttpActionResult时对web api动作方法进行单元测试?

sun*_*nil 129 c# asp.net-web-api asp.net-web-api2

我们假设这是我的行动方法

public IHttpActionResult Get(int id)
{
    var status = GetSomething(id);
    if (status)
    {
        return Ok();
    }
    else
    {
        return NotFound();
    }
}
Run Code Online (Sandbox Code Playgroud)

测试将是

var httpActionResult = controller.Get(1);
Run Code Online (Sandbox Code Playgroud)

如何在此之后检查我的http状态代码?

Kir*_*lla 186

这里Ok()只是一个帮助类型OkResult,它将响应状态设置为HttpStatusCode.Ok...所以你可以检查你的动作结果的实例是否是OkResult......一些例子(写进来XUnit):

// if your action returns: NotFound()
IHttpActionResult actionResult = valuesController.Get(10);
Assert.IsType<NotFoundResult>(actionResult);

// if your action returns: Ok()
actionResult = valuesController.Get(11);
Assert.IsType<OkResult>(actionResult);

// if your action was returning data in the body like: Ok<string>("data: 12")
actionResult = valuesController.Get(12);
OkNegotiatedContentResult<string> conNegResult = Assert.IsType<OkNegotiatedContentResult<string>>(actionResult);
Assert.Equal("data: 12", conNegResult.Content);

// if your action was returning data in the body like: Content<string>(HttpStatusCode.Accepted, "some updated data");
actionResult = valuesController.Get(13);
NegotiatedContentResult<string> negResult = Assert.IsType<NegotiatedContentResult<string>>(actionResult);
Assert.Equal(HttpStatusCode.Accepted, negResult.StatusCode);
Assert.Equal("some updated data", negResult.Content);
Run Code Online (Sandbox Code Playgroud)

  • 在MSTest`Assert.IsInstanceOfType(httpActionResult,typeof(OkResult));` (63认同)
  • @StanimirYakimov当你将`T`类型的对象传递给'Ok()时,结果类型将是`OkNegotiatedContentResult <T>` (4认同)
  • 另外,对于`Created <T>(url,content)```CreatedNegotiatedContentResult` (2认同)
  • 有关返回不规则代码的IHttpStatusCodes的任何帮助吗?喜欢422?`return new StatusCodeResult((HttpStatusCode)422,this);` (2认同)

psa*_*ton 28

是时候复活一个死的问题了

当前答案都依赖于将响应对象转换为已知类型.不幸的是,如果没有对控制器实现的深入了解,响应似乎没有可用的层次结构或隐式转换路径.考虑以下:

public class MixedCodeStandardController : ApiController {

    public readonly object _data = new Object();

    public IHttpActionResult Get() {
        return Ok(_data);
    }

    public IHttpActionResult Get(int id) {
        return Content(HttpStatusCode.Success, _data);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试课程:

var testController = new MixedCodeStandardController();

var getResult = testController.Get();
var posRes = getResult as OkNegotiatedContentResult<object>;
Assert.IsType<OkNegotiatedContentResult<object>>(getResult);
Assert.AreEqual(HttpStatusCode.Success, posRes.StatusCode);
Assert.AreEqual(testController._data, posRes.Content);

var idResult = testController.Get(1);
var oddRes = getResult as OkNegotiatedContentResult<object>; // oddRes is null
Assert.IsType<OkNegotiatedContentResult<object>>(idResult); // throws failed assertion
Assert.AreEqual(HttpStatusCode.Success, oddRes.StatusCode); // throws for null ref
Assert.AreEqual(testController._data, oddRes.Content); // throws for null ref
Run Code Online (Sandbox Code Playgroud)

从黑匣子外面,响应流基本相同.测试必须知道控制器如何实现返回调用以这种方式测试它.

而是使用返回的IHttpActionResult中的HttpResponseMessage对象.这确保了测试可以保持一致,即使控制器代码可能不是:

var testController = new MixedCodeStandardController();

var getResult = testController.Get();
var getResponse = getResult.ExecuteAsync(CancellationToken.None).Result;
Assert.IsTrue(getResponse.IsSuccessStatusCode);
Assert.AreEqual(HttpStatusCode.Success, getResponse.StatusCode);

var idResult = testController.Get(1);
var idResponse = idResult.ExecuteAsync(CancellationToken.None).Result;
Assert.IsTrue(idResponse.IsSuccessStatusCode);
Assert.AreEqual(HttpStatusCode.Success, idResponse.StatusCode);
Run Code Online (Sandbox Code Playgroud)

  • 我必须做的一件事情才能使类似的工作(使用IHttpActionResult.ExecuteAsync方法)将ApiController.Request属性设置为以下内容:`new HttpRequestMessage(){Properties = {{HttpPropertyKeys.HttpConfigurationKey,new HttpConfiguration() }}}` (2认同)

Sta*_*lav 15

这是Kiran Challa接受的,适用于NUnit的答案;

var valuesController = controller;
// if your action returns: NotFound()
IHttpActionResult actionResult = valuesController.Get(10);
var notFoundRes = actionResult as NotFoundResult;
Assert.IsNotNull(notFoundRes);

// if your action returns: Ok()
actionResult = valuesController.Get(11);
var posRes = actionResult as OkResult;
Assert.IsNotNull(posRes);

// if your action was returning data in the body like: Ok<string>("data: 12")
actionResult = valuesController.Get(12);
var conNegResult = actionResult as OkNegotiatedContentResult<string>;
Assert.IsNotNull(conNegResult);
Assert.AreEqual("data: 12", conNegResult.Content);

// if your action was returning data in the body like: Content<string>(HttpStatusCode.Accepted, "some updated data");
actionResult = valuesController.Get(13);
var negResult = actionResult as NegotiatedContentResult<string>;
Assert.IsNotNull(negResult);
Assert.AreEqual(HttpStatusCode.Accepted, negResult.StatusCode);
Assert.AreEqual("some updated data", negResult.Content);
Run Code Online (Sandbox Code Playgroud)