我想对异步控制器进行单元测试。我以前做了很多次,但从未调用Url.Link()
方法来生成位置标题。
继承我的演示代码。
public class DemoController : ApiController
{
[HttpPost]
public async Task<IHttpActionResult> DemoRequestPost(string someRequest)
{
// do something await ...
var id = 1;
// generate url for location header (here the problem occurrs)
var url = Url.Link("DemoRequestGet", new {id = id});
return Created(url, id);
}
[HttpGet]
[Route("demo/{id}", Name = "DemoRequestGet")]
public async Task<IHttpActionResult> DemoRequestGet(int id)
{
// return something
return Ok();
}
}
[TestFixture]
public class DemoControllerTests
{
[Test]
public async Task CreateFromDraftShouldSucceed()
{
// Arrange
var request = "Hello World";
var controller = new DemoController();
var httpConfiguration = new HttpConfiguration();
// ensure attribte routing is setup
httpConfiguration.MapHttpAttributeRoutes();
httpConfiguration.EnsureInitialized();
controller.Configuration = httpConfiguration;
// Act
var result = await controller.DemoRequestPost(request);
// Assert
Assert.AreEqual(result, 1);
}
}
我正在接收
at NUnit.Framework.Internal.ExceptionHelper.Rethrow(异常异常) at NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult) at NUnit.Framework.Internal.Commands.TestMethodCommand.RunAsyncTestMethod(TestExecutionContext context)
答案 0 :(得分:1)
检查Unit Testing Controllers in ASP.NET Web API 2
中的测试链接生成UrlHelper类需要请求URL和路由数据,所以测试 必须为这些设置值。
您没有在示例中设置这些错误。
以下是他们的一个例子
[TestMethod]
public void PostSetsLocationHeader()
{
// Arrange
ProductsController controller = new ProductsController(repository);
controller.Request = new HttpRequestMessage {
RequestUri = new Uri("http://localhost/api/products")
};
controller.Configuration = new HttpConfiguration();
controller.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
controller.RequestContext.RouteData = new HttpRouteData(
route: new HttpRoute(),
values: new HttpRouteValueDictionary { { "controller", "products" } });
// Act
Product product = new Product() { Id = 42, Name = "Product1" };
var response = controller.Post(product);
// Assert
Assert.AreEqual("http://localhost/api/products/42", response.Headers.Location.AbsoluteUri);
}
基于那篇文章你可以做类似的事情,用Moq模仿UrlHelper
。
[TestClass]
public class DemoControllerTests {
[TestMethod]
public async Task CreateFromDraftShouldSucceed() {
// This version uses a mock UrlHelper.
// Arrange
var controller = new DemoController();
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
string locationUrl = "http://localhost/api/demo/1";
// Create the mock and set up the Link method, which is used to create the Location header.
// The mock version returns a fixed string.
var mockUrlHelper = new Mock<UrlHelper>();
mockUrlHelper.Setup(x => x.Link(It.IsAny<string>(), It.IsAny<object>())).Returns(locationUrl);
controller.Url = mockUrlHelper.Object;
// Act
var request = "Hello World";
var result = await controller.DemoRequestPost(request);
var response = await result.ExecuteAsync(System.Threading.CancellationToken.None);
// Assert
Assert.AreEqual(locationUrl, response.Headers.Location.AbsoluteUri);
}
}
答案 1 :(得分:0)
@dknaack对于您的控制器测试,您可能不需要这行代码:
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
httpConfiguration.EnsureInitialized();
controller.Configuration = httpConfiguration;