12

我終於能夠通過在線查找一些代碼來獲得HttpContext.Current不爲空。但我仍然無法在單元測試中爲請求添加自定義標頭。這是我的測試:需要在單元測試中添加自定義頭部請求

[TestClass] 
public class TagControllerTest 
{ 
    private static Mock<IGenericService<Tag>> Service { get; set; } 
    private TagController controller; 

    [TestInitialize] 
    public void ThingServiceTestSetUp() 
    { 
     Tag tag = new Tag(1, "people"); 
     Response<Tag> response = new Response<Tag>(); 
     response.PayLoad = new List<Tag>() { tag }; 

     Service = new Mock<IGenericService<Tag>>(MockBehavior.Default); 
     Service.Setup(s => s.FindAll("username", "password", "token")).Returns(response); 

     controller = new TagController(Service.Object); 
     HttpContext.Current = FakeHttpContext(); 
    } 

    public static HttpContext FakeHttpContext() 
    { 
     var httpRequest = new HttpRequest("", "http://kindermusik/", ""); 
     var stringWriter = new StringWriter(); 
     var httpResponce = new HttpResponse(stringWriter); 
     var httpContext = new HttpContext(httpRequest, httpResponce); 

     var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(), 
               new HttpStaticObjectsCollection(), 10, true, 
               HttpCookieMode.AutoDetect, 
               SessionStateMode.InProc, false); 

     httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, 
            null, CallingConventions.Standard, 
            new[] { typeof(HttpSessionStateContainer) }, 
            null) 
          .Invoke(new object[] { sessionContainer }); 
     httpContext.Request.Headers["username"] = "username"; //It throws a PlatformNotSupportedException exception 
     httpContext.Request.Headers["password"] = "password"; //.Headers.Add("blah", "blah") throws same error 
     httpContext.Request.Headers["token"] = "token"; //And so to .Headers.Set("blah", "blah") 

     return httpContext; 
    } 

    [TestMethod] 
    public void TagControllerGetTest() 
    { 
     // Arrange 
     Response<Tag> result = controller.Get(); 

     // Assert 
     Assert.AreEqual(true, result.IsSuccess); 
     Assert.AreEqual(1, result.PayLoad.Count); 
     Assert.AreEqual("people", result.PayLoad[0].Name); 
    } 

這是正在測試的代碼。

public class TagController : ApiController 
{ 
    public IGenericService<Tag> _service; 

    public TagController() 
    { 
     _service = new TagService(); 
    } 

    public TagController(IGenericService<Tag> service) 
    { 
     this._service = service; 
    } 

    // GET api/values 
    public Response<Tag> Get() 
    { 
     HttpContext context = HttpContext.Current; 
     string username = context.Request.Headers["username"].ToString(); 
     string password = context.Request.Headers["password"].ToString(); 
     string token = context.Request.Headers["token"].ToString(); 
     return (Response<Tag>) _service.FindAll(username, password, token); 
    } 
} 
+1

我不喜歡下面@yzicus答案。有誰知道如何將頭添加到模擬請求*沒有*改變所有的源代碼使用HttpContextFactory? –

回答

3

你可以利用這一點,它的工作:

Setting HttpContext.Current.Session in a unit test

用戶安東尼的回答,並在GetMockedHttpContext添加以下代碼:

request.SetupGet(req => req.Headers).Returns(new NameValueCollection()); 

那麼你可以添加:

HttpContextFactory.Current.Request.Headers.Add(key, value); 

由此您可以發佈標題。但不幸的是,你必須使用HttpContextFactory而不是HttpContext的

0

感謝亞當裏德的博客,可以使用反射來修改頁眉集合:MOCK HTTPCONTEXT.CURRENT.REQUEST.HEADERS UNIT TEST

HttpContext.Current = new HttpContext(
new HttpRequest("", "http://tempuri.org", ""), new HttpResponse(new StringWriter())); 

NameValueCollection headers = HttpContext.Current.Request.Headers; 

Type t = headers.GetType(); 
const BindingFlags nonPublicInstanceMethod = BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance; 

t.InvokeMember("MakeReadWrite", nonPublicInstanceMethod, null, headers, null); 
t.InvokeMember("InvalidateCachedArrays", nonPublicInstanceMethod, null, headers, null); 

// eg. add Basic Authorization header 
t.InvokeMember("BaseRemove", nonPublicInstanceMethod, null, headers, new object[] { "Authorization" }); 
t.InvokeMember("BaseAdd", nonPublicInstanceMethod, null, headers, 
    new object[] { "Authorization", new ArrayList{"Basic " + api_key} }); 

t.InvokeMember("MakeReadOnly", nonPublicInstanceMethod, null, headers, null); 
相關問題