我终于能够通过在线查找一些代码来使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);
}
}
答案 0 :(得分:4)
你可以使用它,它适用于:
Setting HttpContext.Current.Session in a unit test
用户Anthony的回答,并在GetMockedHttpContext中添加此代码:
request.SetupGet(req => req.Headers).Returns(new NameValueCollection());
然后你可以添加:
HttpContextFactory.Current.Request.Headers.Add(key, value);
你可以发帖头。但不幸的是,您必须使用HttpContextFactory而不是HttpContext
答案 1 :(得分:1)
感谢Adam Reed的博客,可以使用反思修改Headers集合: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);
答案 2 :(得分:-1)
我相信在 API 控制器方法中您可以使用“请求”属性:
var testValue = this.Request.Headers.GetValues("headerKey").FirstOrDefault();
然后您可以通过这种方式在单元测试中添加测试值:
var controller = new TestController();
controller.Request = new HttpRequestMessage();
controller.Request.Headers.Add("headerKey", "testValue");