在单元测试期间,HttpContext 始终为null,因为它通常由 IIS 填充。你有几个选择。
当然,你可以嘲笑HttpContext,(你真的不应该这样做 - Don't mock HttpContext!!!!他不喜欢被嘲笑!),。你真的应该尽量避免在你的代码中与HttpContext 紧密耦合。尝试将其限制在一个中心区域 (SRP);
相反,弄清楚您想要实现的功能是什么,并围绕它设计一个抽象。这将使您的代码更具可测试性,因为它与HttpContext 的耦合不是那么紧密。
根据您的示例,您正在寻找访问标头值。这只是在使用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;
}
}
现在在您的控制器中,您可以进行抽象,而不是与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
}
}
你可以稍后注入你的具体类型来获得你想要的功能。
为了测试,你可以交换依赖项来运行你的测试。
如果被测试的方法是你的 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
//.....
}
}