C# 带有响应头的单元测试webapi控制器

C# 带有响应头的单元测试webapi控制器,c#,unit-testing,nunit,asp.net-web-api2,moq,C#,Unit Testing,Nunit,Asp.net Web Api2,Moq,我试图学习webapi,但偶然发现了一个问题。我正在进行的培训课程演示了如何通过返回带有下一个和上一个链接的响应头来进行分页。但是,它使用HttpContext.Current.Response.Headers.Add()发回下一个链接、上一个链接和总页面 我还试图为控制器实现单元测试。问题似乎是当运行单元测试时,HttpContext.Current是null。我在某个地方读到,我不应该是webapi的HttpContext.Current,因为它不可测试,但我不确定应该使用什么来代替它 这是

我试图学习webapi,但偶然发现了一个问题。我正在进行的培训课程演示了如何通过返回带有下一个和上一个链接的响应头来进行分页。但是,它使用
HttpContext.Current.Response.Headers.Add()
发回下一个链接、上一个链接和总页面

我还试图为控制器实现单元测试。问题似乎是当运行单元测试时,
HttpContext.Current
null
。我在某个地方读到,我不应该是webapi的
HttpContext.Current
,因为它不可测试,但我不确定应该使用什么来代替它

这是我的控制器代码:

public partial class CandidateManagerController
{
    private readonly ICandidateManager _candidateManagerV2;

    public CandidateManagerController(ICandidateManager candidateManager)
    {
        _candidateManagerV2 = candidateManager;
    }

    [VersionedRoute("CandidateManager", 2, Name="CandidateManagerV2")]
    public IHttpActionResult Get(int page = 1, int pageSize = 1)
    {
        try
        {
            var totalCount = 0;
            var totalPages = 0;

            var result = _candidateManagerV2.GetCandidates(out totalCount, out totalPages, page, pageSize);

            var urlHelper = new UrlHelper(Request);


            var prevLink = page > 1
                ? urlHelper.Link("CandidateManagerV2",
                    new
                    {
                        page = page - 1,
                        pageSize = pageSize,
                    })
                : "";


            var nextLink = page < totalPages ? urlHelper.Link("CandidateManagerV2",
                new
                {
                    page = page + 1,
                    pageSize = pageSize
                }) : "";

            var paginationHeader = new
            {
                currentPage = page,
                pageSize = pageSize,
                totalCount = totalCount,
                totalPages = totalPages,
                previousPageLink = prevLink,
                nextPageLink = nextLink
            };

            HttpContext.Current.Response.Headers.Add("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader));



            return Ok(result);
        }
        catch (Exception exp)
        {
            return InternalServerError();
        }
    }

}
public分部类CandidateManagerController
{
私人只读ICandidateManager _候选经理2;
公共候选人管理控制器(ICANDIDataManager候选人管理器)
{
_candidateManager=candidateManager;
}
[versionedroote(“CandidateManager”,2,Name=“CandidateManager”)]
公共IHttpActionResult获取(int page=1,int pageSize=1)
{
尝试
{
var totalCount=0;
var totalPages=0;
var result=_candidateManagerV2.GetCandidates(out totalCount,out totalPages,page,pageSize);
var urlHelper=新的urlHelper(请求);
var prevLink=页面>1
?urlHelper.Link(“CandidateManagerV2”,
新的
{
第页=第1页,
pageSize=pageSize,
})
: "";
var nextLink=page
这是我的单元测试。请注意,我使用的是Nunit和Moq:

[TestFixture]
public class CandidateManagerControllerV2Tests
{


    [Test]
    [Category("CandidateManagerController Unit Tests")]
    public void Should_Return_List_Of_Candidate_Objects()
    {

        var testList = new List<Candidate>();
        testList.Add(new Candidate() { CandidateId = 1, Name = "Mr", Surname = "Flibble" });
        testList.Add(new Candidate() { CandidateId = 2, Name = "Arnold", Surname = "Rimmer" });

        var totalCount = 0;
        var totalPages = 0;
        var mockManager = new Mock<ICandidateManager>();
        mockManager.Setup(x => x.GetCandidates(out totalCount, out totalPages, It.IsAny<int>(), It.IsAny<int>())).Returns(testList);

        var controller = new CandidateManagerController(mockManager.Object);
        SetupControllerForTests(controller);

        var result = controller.Get(1, 1);
    }

    private static void SetupControllerForTests(ApiController controller)
    {
        var config = new HttpConfiguration();
        var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/candidatemanager");
        var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
        var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } });

        controller.ControllerContext = new HttpControllerContext(config, routeData, request);
        controller.Request = request;
        controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
        controller.ActionContext=new HttpActionContext();
    }

}
[TestFixture]
公共类候选人管理控制2测试
{
[测试]
[类别(“候选管理控制器单元测试”)]
public void应该返回候选对象的列表()
{
var testList=新列表();
Add(new Candidate(){CandidateId=1,Name=“Mr”,Name=“Flibble”});
Add(new Candidate(){CandidateId=2,Name=“Arnold”,Name=“Rimmer”});
var totalCount=0;
var totalPages=0;
var mockManager=new Mock();
Setup(x=>x.GetCandidates(out totalCount,out totalPages,It.IsAny(),It.IsAny()).Returns(testList);
var控制器=新候选管理器控制器(mockManager.Object);
设置控制器端口(控制器);
var result=controller.Get(1,1);
}
专用静态无效设置控制器端口(ApiController控制器)
{
var config=新的HttpConfiguration();
var request=new-HttpRequestMessage(HttpMethod.Post)http://localhost/api/candidatemanager");
var route=config.Routes.maphttroute(“DefaultApi”、“api/{controller}/{id}”);
var routeData=新的HttpRouteData(路由,新的HttpRouteValueDictionary{{{“控制器”,“产品”});
controller.ControllerContext=新的HttpControllerContext(配置、路由数据、请求);
controller.Request=请求;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey]=config;
controller.ActionContext=新的HttpActionContext();
}
}

我希望有人能帮助我。可能是我在实现分页的方法上走错了路。但是,我可能需要以任何方式添加响应头。

您应该避免将自己耦合到
HttpContext

下面是另一种方法,说明如何设置头并仍然能够按预期对其进行单元测试。您可以创建一个
HttpResponseMessage
,根据需要添加标题,然后从中创建一个
ResponseMessageResult

//…为简洁起见删除了代码
var response=Request.CreateResponse(HttpStatusCode.OK,结果);
Add(“X-Pagination”,Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader));
IHttpActionResult ok=响应消息(响应);
返回ok;
您还应注意,在创建UrlHelper时,控制器设置将导致空引用错误,因为在分配默认的
ActionContext

专用静态无效设置控制器端口测试(ApiController控制器){
var config=新的HttpConfiguration();
var request=new-HttpRequestMessage(HttpMethod.Post)http://localhost/api/candidatemanager");
var route=config.Routes.maphttroute(“DefaultApi”、“api/{controller}/{id}”);
var routeData=新的HttpRouteData(路由,新的HttpRouteValueDictionary{{{“控制器”,“产品”});
controller.ControllerContext=新的HttpControllerContext(配置、路由数据、请求);
controller.Request=请求;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey]=config;
//注释掉这个,因为它导致请求为空
//controller.ActionContext=新的HttpActionContext();
}
检查
X-Pagination
标题时,以下测试通过

公共异步任务应返回_