我对.NET Web Api没有多少经验,但我现在已经使用它了一段时间,遵循John Papa关于Pluralsight的SPA应用程序教程。该应用程序工作正常,但我现在正在努力的是单元测试POST控制器。
我已经按照这个令人难以置信的指南来介绍如何对web api控制器进行单元测试。对我来说唯一的问题是测试POST方法。
我的控制器看起来像这样:
[ActionName("course")]
public HttpResponseMessage Post(Course course)
{
if (course == null)
throw new HttpResponseException(HttpStatusCode.NotAcceptable);
try
{
Uow.Courses.Add(course);
Uow.commit();
}
catch (Exception)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var response = Request.CreateResponse(HttpStatusCode.Created, course);
string uri = Url.Link(routeName: "ControllerActionAndId",
routeValues: new { id = course.Id });
response.Headers.Location = new Uri(uri);
return response;
}
我的单元测试看起来像这样:
[Test]
public void PostShouldReturnHttpResponse()
{
var populatedPostController = new CoursesController(new TestUOW());
SetupPostControllerForTest(populatedPostController);
var course = new Course
{
Id = 12,
Author = new UserProfile()
{
Firstname = "John",
Lastname = "Johnson",
},
Description = "Testcourse",
Title = "Test Title"
};
var responses = populatedPostController.Post(course);
ObjectContent content = responses.Content as ObjectContent;
Course result = (Course)content.Value;
Assert.AreSame(result, course);
}
使用帮助功能:
public static void SetupPostControllerForTest(ApiController controller)
{
var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/courses/course");
var route = config.Routes.MapHttpRoute(
name: "ControllerActionAndId",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: null,
constraints: new { id = @"^\d+$" }
);
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "courses" }, { "action", "course" } });
controller.ControllerContext = new HttpControllerContext(config, routeData, request);
controller.Request = request;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
}
当我调试单元测试时,似乎失败了:
string uri = Url.Link(routeName: "ControllerActionAndId",
routeValues: new { id = course.Id });
response.Headers.Location = new Uri(uri); //Exception because uri = null
似乎Url.Link找不到路线。
我也尝试了this指南,但我真的想要上面的例子。
我错过了一些非常基本的东西吗?
答案 0 :(得分:4)
是的,你错过了Nemesv提到的配置中的一行。
controller.Request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData
如您所见,仅为使用UrlHelper配置控制器非常复杂。出于这个原因,我倾向于避免在控制器类中使用UrlHelper。我通常会引入一个外部依赖项来使测试变得更容易,就像IUrlHelper一样,它允许我模拟单元测试中的行为。
public interface IUrlHelper
{
string Link(string routeName, object routeValues);
string Route(string routeName, object routeValues);
}
public class UrlHelperWrapper : IUrlHelper
{
UrlHelper helper;
public UrlHelperWrapper(UrlHelper helper)
{
this.helper = helper;
}
public string Link(string routeName, object routeValues)
{
return this.helper.Link(routeName, routeValues);
}
public string Route(string routeName, object routeValues)
{
return this.helper.Route(routeName, routeValues);
}
}
我在真正的Web API中注入了这个UrlHelperWraper,并在测试中模拟了IUrlHelper接口。通过这样做,您不需要具有路由的所有复杂配置。
此致 巴勃罗。