Asp.net mvc 单元测试时如何模拟/存根或忽略HttpRequest

Asp.net mvc 单元测试时如何模拟/存根或忽略HttpRequest,asp.net-mvc,unit-testing,dependency-injection,moq,Asp.net Mvc,Unit Testing,Dependency Injection,Moq,问题:DeviceDetection在这里有具体的依赖关系,所以我不能对我的控制器进行单元测试。我不想模拟Http请求,因为我只想测试控制器,而不是DeviceDetection模块 如何模拟/避免访问此(Request.ServerVariables[“HTTP\u X\u REWRITE\u URL”].ToString()) 这导致了所有问题。使DeviceDetectiona的DemoController: public class DemoController : Controller

问题:DeviceDetection在这里有具体的依赖关系,所以我不能对我的控制器进行单元测试。我不想模拟Http请求,因为我只想测试控制器,而不是DeviceDetection模块

如何模拟/避免访问此
(Request.ServerVariables[“HTTP\u X\u REWRITE\u URL”].ToString())


这导致了所有问题。

使
DeviceDetection
a的
DemoController

public class DemoController : Controller
{
    private readonly ICommonOperationsRepository _commonRepo;
    public DemoController (ICommonOperationsRepository commonRepo)
    {
        _commonRepo = commonRepo;
    }

    public ActionResult Default()
    {
        var model = new DemoModel();
        try
        {
            **DeviceDetection dd = new DeviceDetection(Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString());
            dd.DetectDevice();**

            model.ListTopListing.AddRange(_commonRepo.GetListings());
        }
        catch (Exception ex)
        {
            ExceptionHandler objErr = new ExceptionHandler(ex, "DemoController .Default()\n Exception : " + ex.Message);
            objErr.LogException();
        }
        return View(model);
    }
}
这将使您能够创建
DemoController
的实例,而无需依赖
请求
属性:

public class DemoController : Controller
{
    private readonly ICommonOperationsRepository _commonRepo;
    private readonly DeviceDetection dd;

    public DemoController (
        ICommonOperationsRepository commonRepo,
        DeviceDetection dd)
    {
        _commonRepo = commonRepo;
        this.dd = dd;
    }

    public ActionResult Default()
    {
        var model = new DemoModel();
        try
        {
            this.dd.DetectDevice();
            model.ListTopListing.AddRange(_commonRepo.GetListings());
        }
        catch (Exception ex)
        {
            ExceptionHandler objErr = new ExceptionHandler(ex, "DemoController .Default()\n Exception : " + ex.Message);
            objErr.LogException();
        }
        return View(model);
    }
}
您可以在单元测试中这样做


在应用程序中编写
DemoController
时,将
request.ServerVariables[“HTTP\u X\u REWRITE\u URL”].ToString()
传递到
DeviceDetection
。您可以从的
requestContext
参数中获取
request
变量。

要回答您的问题,您需要在测试中执行以下操作:

var sut = new DemoController(someStupRepository, new DeviceDetection("foo"));
使用TransientLifetimeManager注册
DeviceDetector

那么你的控制器应该是这样的

container.RegisterType<IDeviceDetector, DeviceDetector>(new InjectionConstructor(
HttpContext.Current.Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString()));
注意,在这种情况下,您需要为Unity容器编写单元测试,以验证注入是否正确解析。您的单元测试可能如下所示:

public class DemoController : Controller
{
    private readonly ICommonOperationsRepository _commonRepo;
    private readonly IDeviceDetection _deviceDetection;

    public DemoController (
        ICommonOperationsRepository commonRepo,
        IDeviceDetection deviceDetection)
    {
        _commonRepo = commonRepo;
        _deviceDetection = deviceDetection;
    }

    public ActionResult Default()
    {
        var model = new DemoModel();

        _deviceDetection.DetectDevice();
        model.ListTopListing.AddRange(_commonRepo.GetListings());

        return View(model);
    }
}
[TestMethod]
公开无效测试()
{
var repository=newmock();
var deviceDetection=new Mock();
var controller=new DemoController(repository.Object,deviceDetection.Object);
controller.Default();
deviceDetection.Verify(x=>x.DetectDevice(),Times.Once());
}

当我构建DetectDevice时,它会立即给我空引用异常。您能发布测试的代码吗?var usedController=new usedController(new CommonOperationsRepository());var requestBase=new Mock();Setup(r=>r.ServerVariables).Returns(newnamevalueCollection{{{“HTTP_X_REWRITE_URL”,“/used/”});var httpContext=new Mock();Setup(x=>x.Request).Returns(requestBase.Object);var ctrCtx=新模拟();Setup(x=>x.HttpContext).Returns(HttpContext.Object);usedController.ControllerContext=ctrCtx.Object;usedController.Default();这是代码。请不要混淆使用过的/演示过的控制器。我不知道如何/从何处准确地实例化控制器。我知道如何进行单元测试,但如何进行原始控制器定义?您已经依赖于
DemoController
中的
ICommonOperationsRepository
。您是如何编写的?我已经在Unity Bootstraper文件中放置了:container.RegisterType(),我不知道Unity的MVC集成(如果有的话)是如何工作的,但是使用它很简单。实现
IControllerFactory
,它提供了您需要的所有构建块。这不起作用,因为我必须跳过/模拟detectdevice方法的实现,因为它访问一些我不想从单元测试中传递的HttpContext变量。
public class DemoController : Controller
{
    private readonly ICommonOperationsRepository _commonRepo;
    private readonly IDeviceDetection _deviceDetection;

    public DemoController (
        ICommonOperationsRepository commonRepo,
        IDeviceDetection deviceDetection)
    {
        _commonRepo = commonRepo;
        _deviceDetection = deviceDetection;
    }

    public ActionResult Default()
    {
        var model = new DemoModel();

        _deviceDetection.DetectDevice();
        model.ListTopListing.AddRange(_commonRepo.GetListings());

        return View(model);
    }
}
[TestMethod]
public void Test()
{
    var repository = new Mock<ICommonOperationsRepository>();
    var deviceDetection = new Mock<IDeviceDetection>();

    var controller = new DemoController(repository.Object, deviceDetection.Object);
    controller.Default();

    deviceDetection.Verify(x => x.DetectDevice(), Times.Once());
}