我对单元测试非常非常新,并且正在尝试为一个非常简单的方法编写测试:
public class myClass : RequireHttpsAttribute
{
public override void OnAuthorization(AuthoizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
var header = Convert.ToBoolean(request.Headers["Special-Header-Name"]);
if (!(header || request.IsSecureConnection))
{
HandleNonHttpsRequest(filterContext);
}
}
}
此方法继承自RequireHttpsAttribute
,检查页面是否存在某个标头,如果它丢失或为false,并且页面不安全,则会调用HandleNonHttpsRequest
,否则它什么都不做。
我们正在使用Moq和Nunit进行测试。我找到了一些资源来帮助用Moq构建一个fakeHttpContext,但说实话,我不确定如何使用它或在我的单元测试中去哪里以确保假的HttpContexts是或不是导致HandleNonHttpsRequest
方法呼叫。
我非常感谢您对此问题的任何指导。
答案 0 :(得分:20)
// arrange
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var headers = new NameValueCollection
{
{ "Special-Header-Name", "false" }
};
request.Setup(x => x.Headers).Returns(headers);
request.Setup(x => x.HttpMethod).Returns("GET");
request.Setup(x => x.Url).Returns(new Uri("http://www.example.com"));
request.Setup(x => x.RawUrl).Returns("/home/index");
context.Setup(x => x.Request).Returns(request.Object);
var controller = new Mock<ControllerBase>();
var actionDescriptor = new Mock<ActionDescriptor>();
var controllerContext = new ControllerContext(context.Object, new RouteData(), controller.Object);
var filterContext = new AuthorizationContext(controllerContext, actionDescriptor.Object);
var sut = new myClass();
// act
sut.OnAuthorization(filterContext);
// assert
Assert.IsInstanceOfType(filterContext.Result, typeof(RedirectResult));
var redirectResult = (RedirectResult)filterContext.Result;
Assert.AreEqual("https://www.example.com/home/index", redirectResult.Url);
答案 1 :(得分:1)
是的,我会使用Moq并创建一个Mock<AuthorizationContext>
。您需要一系列模拟对象来设置虚假请求,最明显的是指定伪标题的NameValueCollection。
var request = new Mock<HttpRequestBase>();
request.SetupGet(c => c.Headers).Return(new NameValueCollection{ /* initialize values here */});
request.SetupGet(c => c.IsSecureConnection).Return(/*specify true or false depending on your test */);
var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Return(request.Object);
var filterContext = new Mock<AuthorizationContext>();
filterContext.SetupGet(c => c.HttpContext).Return(httpContext.Object);
var myclass = new myClass();
myClass.OnAuthorization(filterContext.Object);
(对不起,如果语法或用法稍微偏离;从头到尾这样做)
您可能需要进入并模拟HandleNonHttpsRequest调用的filterContext上的任何其他成员。关于这个问题我有两个建议,因为如果你正在测试的方法在filterContext上做了很多复杂的事情,它有时会很麻烦:1)直观地检查,如果它足够直接,那么模拟所有被调用的部分2)创建myClass.OnAuthorizationRequest,但除了调用HandleNonHttpsRequest之外,不要实现任何代码。继续运行测试并修复丢失/错误模拟的成员,直到测试通过。然后实现OnAuthorizationRequest的实际逻辑,测试和修复(冲洗重复)直到它通过。
答案 2 :(得分:0)
我在使用ASP.NET MVC 4时遇到了the accepted solution的问题。要解决它,我模拟了http上下文Items属性,否则sut.OnAuthorization
导致对象是未定义的异常:
MockHttpContext.Setup(x => x.Items)
.Returns(new System.Collections.Generic.Dictionary<object, object>());