用于单元测试的模拟 HttpActionContext
Mock HttpActionContext for Unit Test
我有一个自定义授权属性,如下所示,我正在尝试编写单元测试来测试其功能。
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization != null)
{
// get the Authorization header value from the request and base64 decode it
string userInfo = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter));
// custom authentication logic
if (string.Equals(userInfo, string.Format("{0}:{1}", "user", "pass")))
{
IsAuthorized(actionContext);
}
else
{
HandleUnauthorizedRequest(actionContext);
}
}
else
{
HandleUnauthorizedRequest(actionContext);
}
}
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized)
{
ReasonPhrase = "Unauthorized"
};
}
我的问题是,当我尝试对此进行测试时,我得到 "System.NullReferenceException: Object reference not set to an instance of an object." 我已尝试设置 actionContext 的 request.headers.authorization 值,但它没有 setter。当我尝试模拟 HttpActionContext 时,它说它无法从模拟 HttpActionContext 转换为真实的。下面是我的测试代码
public class HttpBasicAuthorizeAttributeTest
{
private HttpBasicAuthorizeAttribute ClassUnderTest { get; set; }
private HttpActionContext actionContext { get; set; }
[TestMethod]
public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization()
{
var context = new Mock<HttpActionContext>();
context.Setup(x => x.Request.Headers.Authorization.Parameter).Returns("bzUwkDal=");
ClassUnderTest.OnAuthorization(context);
}
[TestInitialize]
public void Initialize()
{
ClassUnderTest = new HttpBasicAuthorizeAttribute();
actionContext = new HttpActionContext();
}
}
*省略断言,直到我什至可以让 HttpActionContext 工作
您可以使用实际对象并将其提供给模拟,以便在无法模拟非虚拟成员的情况下将被测方法作为 Moq 进行测试。
[TestMethod]
public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization() {
//Arrange
var context = new HttpActionContext();
var headerValue = new AuthenticationHeaderValue("Basic", "bzUwkDal=");
var request = new HttpRequestMessage();
request.Headers.Authorization = headerValue;
var controllerContext = new HttpControllerContext();
controllerContext.Request = request;
context.ControllerContext = controllerContext;
//Act
ClassUnderTest.OnAuthorization(context);
//Assert
//...
}
我有一个自定义授权属性,如下所示,我正在尝试编写单元测试来测试其功能。
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization != null)
{
// get the Authorization header value from the request and base64 decode it
string userInfo = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter));
// custom authentication logic
if (string.Equals(userInfo, string.Format("{0}:{1}", "user", "pass")))
{
IsAuthorized(actionContext);
}
else
{
HandleUnauthorizedRequest(actionContext);
}
}
else
{
HandleUnauthorizedRequest(actionContext);
}
}
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized)
{
ReasonPhrase = "Unauthorized"
};
}
我的问题是,当我尝试对此进行测试时,我得到 "System.NullReferenceException: Object reference not set to an instance of an object." 我已尝试设置 actionContext 的 request.headers.authorization 值,但它没有 setter。当我尝试模拟 HttpActionContext 时,它说它无法从模拟 HttpActionContext 转换为真实的。下面是我的测试代码
public class HttpBasicAuthorizeAttributeTest
{
private HttpBasicAuthorizeAttribute ClassUnderTest { get; set; }
private HttpActionContext actionContext { get; set; }
[TestMethod]
public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization()
{
var context = new Mock<HttpActionContext>();
context.Setup(x => x.Request.Headers.Authorization.Parameter).Returns("bzUwkDal=");
ClassUnderTest.OnAuthorization(context);
}
[TestInitialize]
public void Initialize()
{
ClassUnderTest = new HttpBasicAuthorizeAttribute();
actionContext = new HttpActionContext();
}
}
*省略断言,直到我什至可以让 HttpActionContext 工作
您可以使用实际对象并将其提供给模拟,以便在无法模拟非虚拟成员的情况下将被测方法作为 Moq 进行测试。
[TestMethod]
public void HttpBasicAuthorizeAttribute_OnAuthorize_WithAuthorizedUser_ReturnsAuthorization() {
//Arrange
var context = new HttpActionContext();
var headerValue = new AuthenticationHeaderValue("Basic", "bzUwkDal=");
var request = new HttpRequestMessage();
request.Headers.Authorization = headerValue;
var controllerContext = new HttpControllerContext();
controllerContext.Request = request;
context.ControllerContext = controllerContext;
//Act
ClassUnderTest.OnAuthorization(context);
//Assert
//...
}