我有以下 Web Api Controller 方法。
当我通过 Web 运行此代码时,HttpContext.Current
为 never null
并提供所需的值。
public override void Post([FromBody]TestDTO model)
{
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
// more code
}
但是,当我从 Unit Test
调用此方法时,HttpContext.Current 始终为 null。
我该如何解决?
最佳答案
在单元测试期间,HttpContext
始终为 null
,因为它通常由 IIS 填充。你有几个选择。
当然,你可以模拟 HttpContext
,(你真的不应该这样做 - Don't mock HttpContext !!!! 他不喜欢被 mock ! ),.您真的应该尽量避免在整个代码中与 HttpContext
紧密耦合。尝试将其限制在一个中心区域 (SRP);
相反,弄清楚你想要实现的功能是什么,并围绕它设计一个抽象。这将使您的代码更易于测试,因为它与 HttpContext
没有紧密耦合。
根据您的示例,您希望访问 header 值。这只是一个示例,说明在使用 HttpContext
时如何改变您的想法。
你原来的例子有这个
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
当你正在寻找这样的东西时
var testName = myService.GetOsType();
然后创建一个提供该服务的服务
public interface IHeaderService {
string GetOsType();
}
它可以有一个具体的实现,比如
public class MyHeaderService : IHeaderService {
public string GetOsType() {
var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
return testName;
}
}
现在在你的 Controller 中你可以拥有你的抽象而不是与 HttpContext
public class MyApiController : ApiController {
IHeaderService myservice;
public MyApiController(IHeaderService headers) {
myservice = headers;
}
public IHttpActionResult Post([FromBody]TestDTO model) {
var testName = myService.GetOsType();
// more code
}
}
您稍后可以注入(inject)您的具体类型以获得您想要的功能。
为了测试,您然后交换依赖项以运行您的测试。
如果被测方法是您的 Post()
方法,您可以创建一个假的依赖项或使用模拟框架
[TestClass]
public class MyTestClass {
public class MyFakeHeaderService : IHeaderService {
string os;
public MyFakeHeaderService(string os) {
this.os = os;
}
public string GetOsType() {
return os;
}
}
[TestMethod]
public void TestPostMethod() {
//Arrange
IHeaderService headers = new MyFakeHeaderService("FAKE OS TYPE");
var sut = new MyApiController(headers);
var model = new TestDTO();
//Act
sut.Post(model);
//Assert
//.....
}
}
关于c# - 单元测试时 HttpContext.Current 为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38170467/