1

在控制台应用程序中,我想使用通常需要将当前http上下文传递给其构造函数的服务。我使用Ninject,并且我认为我可以简单地伪造一个http上下文并定义合适的绑定,但是我一直在努力挣扎几个小时而没有成功。如何伪造HttpContext及其HttpRequest将它们注入到服务构造函数中

细节:

的服务实际上是来自一个ASP.Net MVC项目的邮寄服务。我也在使用Ninject进行IoC。邮件服务需要将当前的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的所有东西对我来说都是新鲜事物。

回答

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; 
     } 
+1

我以为嘲笑是供测试用。在这里,它不是我正在开发的测试工具,而是一个真正的控制台应用程序。另外,我不确定如何与Ninject一起使用工厂。它是我将传递给服务构造函数而不是实际上下文的上下文工厂吗? –