Mock HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString(“action”)

时间:2014-11-06 05:05:41

标签: c# asp.net-mvc unit-testing mocking nunit

我使用NUnit和Moq框架为我的控制器类编写了一个测试类。我的类正在跟随

public class ClientTypeControllerTest 
{
private Mock<IClientTypeService> _clientTypeServiceMock;
private Mock<IClientTypeAudService> _clientTypeAudServiceMock;
private Mock<IClientTypeHisService> _clientTypeHisServiceMock;
private Mock<HttpSessionStateBase> _sessionMock;
private Mock<HttpResponseBase> _httpresponceMock;
private Mock<IUserAccountService> _userAccountService;

ClientTypeController objClientTypeController;
protected Users LoggedInUser { get; set; }
List<ClientTypeAud> lists;


[SetUp]
public void Initialize()
{
    //System.Diagnostics.Debugger.Launch();
    _clientTypeServiceMock = new Mock<IClientTypeService>();
    _clientTypeAudServiceMock = new Mock<IClientTypeAudService>();
    _clientTypeHisServiceMock = new Mock<IClientTypeHisService>();
    _userAccountService = new Mock<IUserAccountService>();
    _sessionMock = new Mock<HttpSessionStateBase>();
    _httpresponceMock = new Mock<HttpResponseBase>();
    var ctrlContext = new Mock<ControllerContext>();

    AutoMapperConfiguration.Configure();
    _sessionMock.SetupGet(s => s["LOGGED_IN_USER"]).Returns(users);
    ctrlContext.Setup(p => p.HttpContext.Session).Returns(_sessionMock.Object);

}



[Test]
public void Show_AllClientTypeRecords_InGridView_UnitTest()
{
     lists = new List<ClientTypeAud>()  {
     new ClientTypeAud() { Id = 1, CTypeName = "INR", CompanyId = 1, Active = "Y" },
     new ClientTypeAud() { Id = 1, CTypeName = "ABC", CompanyId = 1, Active = "Y" },
     new ClientTypeAud() { Id = 1, CTypeName = "AVM", CompanyId = 1, Active = "Y" }
   };

    _clientTypeAudServiceMock.Setup(x => x.All()).Returns(lists.AsQueryable());
    objClientTypeController = new ClientTypeController(_clientTypeServiceMock.Object, 
                  _clientTypeAudServiceMock.Object, _clientTypeHisServiceMock.Object, 
                                                       _userAccountService.Object);

var result = objClientTypeController.GridData("", "asc", 1, 1) as JsonResult;
    Assert.IsNotNull(result.Data);
 }
}

我的BaseController类是,

public class BaseController : Controller
{
public SessionProvider SessionProvider;
protected Users LoggedInUser { get; set; }

public string actionName { get; set; }        
protected string controllerName { get; set; }
protected string area { get; set; }

public BaseController()
{
    actionName = 
 System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString("action");
    controllerName = 
      System.Web.HttpContext.Current.Request.RequestContext.RouteData.
                                                GetRequiredString("controller");
    SessionProvider = new SessionProvider(Session);
    LoginMethod();            
    ViewBag.Menu = BuildMenu();

}
 ......
  ......

当我使用NUnit运行我的测试类时,它显示Nullreferenceexception未被用户代码处理

  actionName = System.Web.HttpContext.Current.Request.RequestContext.
                             RouteData.GetRequiredString("action");

这是在我的BaseControllerClass中。所以我不知道如何为HqpContext.Current.Request.RequestContext.so提供数据。请有人请帮助找到解决方案

3 个答案:

答案 0 :(得分:1)

你应该为HttpContext操作创建一个包装器,并使用像Rhino Mocks这样的框架模拟UT中的包装调用(通过使用接口)。

您将使用一种方法创建一个接口IHttpContextWrapper&#34; string GetRequiredStringFromRequestRouteData(string valueName)&#34;。

之后,您应该创建接口的实现。说&#34;公共类HttpContextWrapper:IHttpContextWrapper&#34;并且你将在GetRequiredStringFromRequestRouteData的实现中使用HttpContext.Current.Request.RequestContext.RouteData.GetRequiredData(valueName)。

在您的客户端类中,您可以使用依赖注入(通过使用Spring.NET框架或Unity)注入要由属性或构造函数使用的实现。

但是,当你在单元测试中测试客户端时,你将注入一个基于接口创建的模拟对象,你将模拟调用&#34; GetRequiredStringFromRequestRouteData&#34;回报你想要的任何东西。你可以使用像Rhino Mocks这样的Mocking框架来做到这一点。

答案 1 :(得分:1)

您应该为System.Web.dll添加Fakes Assembly

在解决方案资源管理器中,展开单元测试项目的参考文献。

  1. 如果您使用的是Visual Basic,则必须在“解决方案资源管理器”工具栏中选择“显示所有文件”,以便查看“参考”列表。
  2. 选择包含要为其创建填充程序的类定义的程序集。例如,如果要填充HttpContext,请选择System.Web.dll
  3. 在快捷菜单上,选择Add Fakes Assembly。
  4. 然后创建一个shimcontext并在该上下文中模拟/绕开所需方法的执行。

    [TestMethod]
    public void TestCurrentYear()
    {
        using(ShimContext.Create()) 
        {
            // Arrange:
            System.Web.Fakes.ShimHttpContext....
        }
    }
    

    来源:http://msdn.microsoft.com/en-us/library/hh549176.aspx

    OR

    您可以使用AspNet Simulator尝试不同的方法,该模拟器专门用于在Mvc应用程序的控制器级别进行单元测试。可以在这里找到一个例子: https://github.com/ibrahimbensalah/Xania.AspNet.Simulator/tree/master/Xania.AspNet.Simulator.Tests

答案 2 :(得分:1)

在设置RouteData之前,您需要伪造您的HttpContext。最简单的方法是

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://localhost/", ""), 
    new HttpResponse(new StringWriter()));

现在您可以编写RequestContext以满足您的要求。首先模拟HttpContext,然后创建RouteData实例。

var contextBase = new Mock<HttpContextBase>();
var routeData = new RouteData();
routeData.Values["controller"] = "anyControllerNameYouWant";
routeData.Values["action"] = "anyActionNameYouWant";

最后一个,只需将这些分配给你的假HttpContext.Current并完成。

HttpContext.Current.Request.RequestContext = new 
    RequestContext(contextBase.Object, routeData);