在一个控制器模拟服务器 [英] Mock server in a Controller

查看:147
本文介绍了在一个控制器模拟服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下线在我的控制器:

 字符串lTempPath = Path.Combine(使用Server.Mappath(〜/温度),lRandomFileName);

问题是服务器是不是虚拟的,只能用一个getter访问。

我收到了


  

的方法或操作未实现。


我怎么能嘲笑这台服务器?

我所创建的测试如下:

  [TestCase的]
    公共无效previewActionShouldGenerateUrlOfPdf()
    {
        //安排
        VAR服务器= MockRepository.GenerateMock<&的HttpServerUtilityBase GT;();
        server.Stub(S = GT; s.MapPath(〜temp的))返回(〜/ temp的)。
        VAR的HttpContext = MockRepository.GenerateMock< HttpContextBase>();
        httpContext.Stub(HC = GT; hc.Server).Return(服务器);
        httpContext.Server.Stub(S = GT; s.MapPath(〜/温度))返回(〜/ temp的)。        VAR控制器=新StudiesController()
        {
            ReportingService = MockRepository.GenerateMock< IReportingService>()
            SecurityService = MockRepository.GenerateMock< ISecurityService>()
        };
        controller.ControllerContext =新的ControllerContext(HttpContext的,新的RouteData(),控制器);        controller.ReportingService.Stub(RS => rs.GetStudyByGID(新的GUID()))返回(新研究());
        controller.ReportingService.Stub(RS => rs.ListPractices())返回(新[] {新实践(),新实践()});
        controller.SecurityService.Stub(SS => ss.GetUser())。IgnoreArguments()返回(新用户());        controller.ControllerContext.HttpContext = MockRepository.GeneratePartialMock&所述; FakeHttpContext&GT(http://test.com);
        controller.HttpContext.User =新FakePrincipal(新FakeIdentity(测试),新的字符串[0]);
        controller.ControllerContext.HttpContext.Stub(X => x.Request).Return(MockRepository.GenerateMock&下; Htt的prequestBase>());
        controller.ControllerContext.HttpContext.Request.Stub(X => x.Url).Return(新的URI(http://test.com));        controller.ReportingService.Stub(
            RS =>
            rs.GenerateReport(新研究(),新实践(),新用户(),假的,ReportGenerationOutputFormat.PDF))IgnoreArguments()返回(新StudyReportSnapshot());        VAR内容=新ContentResult类型();        //法案        VAR的结果=(ContentResult类型)控制器preVIEW(新的GUID());        //断言
        Assert.AreEqual(result.Content,content.Content);    }


解决方案

假设你正在使用某种IOC / DI容器,你不应该依赖于 Controller.Server 。相反,你应该使用的HttpServerUtilityBase

这个例子假定Ninject作为IOC容器,但任何流行的容器会做什么:

首先,注册的HttpServerUtilityBase 与IOC容器像这样:

  kernel.Bind<&的HttpServerUtilityBase GT;()ToMethod(C =>新建HttpServerUtilityWrapper(HttpContext.Current.Server))。

这将确保在运行时,您的应用程序将使用当前请求的服务器属性。

然后,添加一个构造函数到控制器接受的一个实例的HttpServerUtilityBase

 公共myController的(服务器的HttpServerUtilityBase)
{
    this._server =服务器;
}

现在,你在哪里调用之前的任何地方使用Server.Mappath ,只需拨打 _server.MapPath 代替。

最后,在你的测试,你可以嘲笑的HttpServerUtilityBase像这样(假设起订量为模拟框架):

  VAR服务器=新的模拟<&的HttpServerUtilityBase GT;();
server.Setup(S => s.MapPath(It.IsAny<串>()))返回<串>(S => / *设置你怎么想的MapPath在这里* /行为);

修改

既然你提到你不使用DI框架,可以求助于穷人的依赖注入。本质上添加一个重载的构造函数:

 公共myController的()
    :这(新HttpServerUtilityWrapper(HttpContext.Current.Server))
{
}公共myController的(服务器的HttpServerUtilityBase)
{
    this._server =服务器;
}

这将使生产code使用当前Web请求,但你可以创建自己的实现的HttpServerUtilityBase 的使用进行测试。

I have the following line in my controller:

string lTempPath = Path.Combine(Server.MapPath("~/Temp"), lRandomFileName);

Problem is Server is not virtual and can only be accessed with a getter.

I get a

"The method or operation is not implemented."

How can I mock this server?

The test I have created is as below:

    [TestCase]
    public void PreviewActionShouldGenerateUrlOfPdf()
    {
        //Arrange
        var server = MockRepository.GenerateMock<HttpServerUtilityBase>();
        server.Stub(s => s.MapPath("~Temp")).Return("~/Temp");
        var httpContext = MockRepository.GenerateMock<HttpContextBase>();
        httpContext.Stub(hc => hc.Server).Return(server);
        httpContext.Server.Stub(s => s.MapPath("~/Temp")).Return("~/Temp");

        var controller = new StudiesController()
        {
            ReportingService = MockRepository.GenerateMock<IReportingService>(),
            SecurityService = MockRepository.GenerateMock<ISecurityService>()
        };


        controller.ControllerContext = new ControllerContext(httpContext, new RouteData(), controller);

        controller.ReportingService.Stub(rs => rs.GetStudyByGID(new Guid())).Return(new Study());
        controller.ReportingService.Stub(rs => rs.ListPractices()).Return(new[] { new Practice(), new Practice() });
        controller.SecurityService.Stub(ss => ss.GetUser("")).IgnoreArguments().Return(new User());

        controller.ControllerContext.HttpContext = MockRepository.GeneratePartialMock<FakeHttpContext>("http://test.com");
        controller.HttpContext.User = new FakePrincipal(new FakeIdentity("test"), new string[0]);
        controller.ControllerContext.HttpContext.Stub(x => x.Request).Return(MockRepository.GenerateMock<HttpRequestBase>());
        controller.ControllerContext.HttpContext.Request.Stub(x => x.Url).Return(new Uri("http://test.com"));



        controller.ReportingService.Stub(
            rs =>
            rs.GenerateReport(new Study(), new Practice(), new User(), false, ReportGenerationOutputFormat.PDF)).IgnoreArguments().Return(new StudyReportSnapshot());

        var content = new ContentResult();

        //Act

        var result = (ContentResult)controller.Preview(new Guid());

        //Assert
        Assert.AreEqual(result.Content, content.Content);

    }

解决方案

Assuming you're using some sort of IOC/DI container, you shouldn't depend on Controller.Server. Instead you should use HttpServerUtilityBase.

This example assumes Ninject as the IOC container, but any of the popular containers will do:

First, register HttpServerUtilityBase with your IOC container like so:

kernel.Bind<HttpServerUtilityBase>().ToMethod(c => new HttpServerUtilityWrapper(HttpContext.Current.Server));

This will make sure that at run time your app will use the current request's server property.

Then, add a constructor to your controller that accepts an instance of HttpServerUtilityBase:

public MyController(HttpServerUtilityBase server)
{
    this._server = server;
}

Now, anywhere before where you were calling Server.MapPath, just call _server.MapPath instead.

Finally, in your tests, you can mock HttpServerUtilityBase like so (assuming Moq as the mocking framework):

var server = new Mock<HttpServerUtilityBase>();
server.Setup(s => s.MapPath(It.IsAny<string>())).Returns<string>(s => /* set up how you want MapPath to behave here */);

EDIT

Since you mentioned you're not using an DI framework, you can resort to "Poor Man's Dependency Injection". Essentially adding an overloaded constructor:

public MyController()
    : this(new HttpServerUtilityWrapper(HttpContext.Current.Server))
{
}

public MyController(HttpServerUtilityBase server)
{
    this._server = server;
}

This will allow production code to use the current web request, but then you can create your own implementation of HttpServerUtilityBase to use for testing.

这篇关于在一个控制器模拟服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆