1

在控制台应用程序中,我想使用通常需要将当前 http 上下文传递给其构造函数的服务。我正在使用 Ninject,我想我可以简单地伪造一个 http 上下文并定义正确的绑定,但是我已经为此苦苦挣扎了几个小时而没有成功。

细节:

该服务实际上是一个来自 ASP.Net MVC 项目的邮件服务。我也在为 IoC 使用 Ninject。邮件服务需要将当前的 http 上下文传递给它的构造函数。我按如下方式进行绑定:

kernel.Bind<IMyEmailService>().To<MyEmailService>()
    .WithConstructorArgument("httpContext", ninjectContext => new HttpContextWrapper(HttpContext.Current));

但是,我现在想在控制台应用程序中使用此邮件服务,该应用程序将用于在夜间运行自动化任务。为了做到这一点,我想我可以简单地伪造一个 http 上下文,但我已经为此苦苦挣扎了几个小时。

上下文中的所有邮件服务需求都是这两个属性:

  • httpContext.Request.UserHostAddress
  • httpContext.Request.RawUrl

我以为我可以做这样的事情,但是:

定义我自己的假请求类:

public class AutomatedTaskHttpRequest : SimpleWorkerRequest
{
    public string UserHostAddress;
    public string RawUrl;

    public AutomatedTaskHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output)
        : base(appVirtualDir, appPhysicalDir, page, query, output)
    {
        this.UserHostAddress = "127.0.0.1";
        this.RawUrl = null;
    }
}

定义我自己的上下文类:

public class AutomatedTasksHttpContext
{
    public AutomatedTaskHttpRequest Request;

    public AutomatedTasksHttpContext()
    {
        this.Request = new AutomatedTaskHttpRequest("", "", "", null, new StringWriter());
    }
}

并在我的控制台应用程序中按如下方式绑定它:

   kernel.Bind<IUpDirEmailService>().To<UpDirEmailService>()
        .WithConstructorArgument("httpContext", ninjectContext => new AutomatedTasksHttpContext());

不幸的是,这行不通。我尝试了各种变体,但没有一个有效。请多多包涵。所有 IoC 的东西对我来说都很新鲜。

4

1 回答 1

3

我最近回答了关于使用 HttpContextFactory 进行测试的问题,它对控制台应用程序同样采用了不同的方法。

public static class HttpContextFactory
    {
        [ThreadStatic]
        private static HttpContextBase _serviceHttpContext;

        public static void SetHttpContext(HttpContextBase httpContextBase)
        {
            _serviceHttpContext = httpContextBase;
        }

        public static HttpContextBase GetHttpContext()
        {
            if (_serviceHttpContext!= null)
            {
                return _serviceHttpContext;
            }

            if (HttpContext.Current != null)
            {
                return new HttpContextWrapper(HttpContext.Current);
            }
            return null;
        }
    }

然后在你的代码中:

var rawUrl = HttpContextFactory.GetHttpContext().Request.RawUrl;

然后在您的测试中使用该属性作为接缝

HttpContextFactory.SetHttpContext(HttpMocks.HttpContext());

其中 HttpMocks 具有以下内容,并将针对您的测试进行调整:

public static HttpContextBase HttpContext()
      {
          var context = MockRepository.GenerateMock<HttpContextBase>();
          context.Stub(r => r.Request).Return(HttpRequest());
          // and stub out whatever else you need to, like session etc
          return context;
      }


      public static HttpRequestBase HttpRequest()
      {
          var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
          httpRequest.Stub(r => r.UserHostAddress).Return("127.0.0.1"); 
          httpRequest.Stub(r => r.RawUrl).Return(null); 
          return httpRequest;
      }
于 2012-11-19T19:45:28.443 回答