2009-03-24 7 views
4

Je veux mocker la propriété User d'un HttpContext. J'utilise la classe Scott Hanselmans MVCHelper et RhinoMocks.Mocking et HttpContextBase.get_User()

J'ai un test unitaire qui contient le code, comme ceci:

...

MockIdentity fakeId = new MockIdentity("TEST_USER", "Windows", true); 
MockPrincipal fakeUser = new MockPrincipal(null, fakeId); 

using (mocks.Record()) 
{ 
    Expect.Call(fakeHttpContext.User).Return(fakeUser); 
} 

...

Mon MockIdentity et les classes MockPrincipal sont conformes aux simulacres IIdentity et IPrincipal, respectivement.

je reçois une erreur lors de l'exécution du test unitaire qui rapporte:

System.NotImplementedException: La méthode ou opération n'est pas mis en œuvre. à System.Web.HttpContextBase.get_User()

Cela se produit lorsque j'essaie de définir l'attente pour la propriété utilisateur.

Je comprends que le httpContextBase a un getter et un setter qui ne sont pas implémentés mais je pensais que Rhino gérerait cela en se moquant. Cela signifie-t-il que je dois dériver de HttpContextbase et remplacer la propriété de mon objet fantaisie? Cela semble étrange.

D'autres utilisateurs ont eu ce problème et il est rapporté ici: http://www.mail-archive.com/[email protected]/msg00546.html

Répondre

8

Pour se moquer de la propriété utilisateur, vous pouvez le faire:

var httpContext = MockRepository.GenerateStub<HttpContextBase>(); 
httpContext.Stub(x=>x.User).Return(yourFakePrincipalHere); 

var controllerContext = new ControllerContext(httpContext, ....); 

var controller = new HomeController(); 
controller.ControllerContext = controllerContext; 

(celui-ci utilise la nouvelle RM 3.5 api, si vous le faire w/enregistrement/lecture puis:

using(mocks.Record) 
{ 
    _httpContext = _mocks.DynamicMock<HttpContextBase>(); 
    SetupResult.For(_httpContext.User).Return(...); 
} 

using(mocks.PlayBack()) 
{ 
    .... 
} 
+0

Brialliant Ben. À votre santé. Je pense que ma compréhension de Stubs et Mocks a besoin d'être «brossée». J'ai eu un problème avec: httpContext.Stub (x => x.User) .Return (yourFakePrincipalHere); mais remplacé par: httpContext.User - = [fakeUser]; Qui a bien fonctionné. – Lewis

13

J'ai eu à peu près le même problème et déplacé à Moq.

C'est l'aide personnalisée I utilise dans mes applications:

public static class MvcMockHelpers 
    { 
     public static HttpContextBase FakeHttpContext() 
     { 

      var context = new Mock<HttpContextBase>(); 
      var request = new Mock<HttpRequestBase>(); 
      var response = new Mock<HttpResponseBase>(); 
      var session = new Mock<HttpSessionStateBase>(); 
      var server = new Mock<HttpServerUtilityBase>(); 

      context.Expect(ctx => ctx.Request).Returns(request.Object); 
      context.Expect(ctx => ctx.Response).Returns(response.Object); 
      context.Expect(ctx => ctx.Session).Returns(session.Object); 
      context.Expect(ctx => ctx.Server).Returns(server.Object); 


      var form = new NameValueCollection(); 
      var querystring = new NameValueCollection(); 
      var cookies = new HttpCookieCollection(); 
      var user = new GenericPrincipal(new GenericIdentity("testuser"), new string[] { "Administrator" }); 

      request.Expect(r => r.Cookies).Returns(cookies); 
      request.Expect(r => r.Form).Returns(form); 
      request.Expect(q => q.QueryString).Returns(querystring); 

      response.Expect(r => r.Cookies).Returns(cookies); 

      context.Expect(u => u.User).Returns(user); 



      return context.Object; 
     } 

     public static HttpContextBase FakeHttpContext(string url) 
     { 
      HttpContextBase context = FakeHttpContext(); 
      context.Request.SetupRequestUrl(url); 

      return context; 

     } 


     public static void SetFakeControllerContext(this Controller controller) 
     { 
      var httpContext = FakeHttpContext(); 
      ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); 
      controller.ControllerContext = context; 
     } 

     public static void SetFakeControllerContext(this Controller controller, RouteData routeData) 
     { 
      SetFakeControllerContext(controller, new Dictionary<string, string>(), new HttpCookieCollection(), routeData); 
     } 

     public static void SetFakeControllerContext(this Controller controller, HttpCookieCollection requestCookies) 
     { 
      SetFakeControllerContext(controller,new Dictionary<string,string>(),requestCookies, new RouteData()); 
     } 

     public static void SetFakeControllerContext(this Controller controller, Dictionary<string, string> formValues) 
     { 
      SetFakeControllerContext(controller, formValues, new HttpCookieCollection(), new RouteData()); 
     } 

     public static void SetFakeControllerContext(this Controller controller, 
      Dictionary<string, string> formValues, 
      HttpCookieCollection requestCookies, 
      RouteData routeData) 
     { 
      var httpContext = FakeHttpContext(); 

      foreach (string key in formValues.Keys) 
      { 
       httpContext.Request.Form.Add(key, formValues[key]); 

      } 
      foreach (string key in requestCookies.Keys) 
      { 
       httpContext.Request.Cookies.Add(requestCookies[key]); 

      } 
      ControllerContext context = new ControllerContext(new RequestContext(httpContext, routeData), controller); 
      controller.ControllerContext = context; 
     } 

     public static void SetFakeControllerContextWithLogin(this Controller controller, string userName, 
      string password, 
      string returnUrl) 
     { 

      var httpContext = FakeHttpContext(); 


      httpContext.Request.Form.Add("username", userName); 
      httpContext.Request.Form.Add("password", password); 
      httpContext.Request.QueryString.Add("ReturnUrl", returnUrl); 

      ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); 
      controller.ControllerContext = context; 
     } 


     static string GetUrlFileName(string url) 
     { 
      if (url.Contains("?")) 
       return url.Substring(0, url.IndexOf("?")); 
      else 
       return url; 
     } 

     static NameValueCollection GetQueryStringParameters(string url) 
     { 
      if (url.Contains("?")) 
      { 
       NameValueCollection parameters = new NameValueCollection(); 

       string[] parts = url.Split("?".ToCharArray()); 
       string[] keys = parts[1].Split("&".ToCharArray()); 

       foreach (string key in keys) 
       { 
        string[] part = key.Split("=".ToCharArray()); 
        parameters.Add(part[0], part[1]); 
       } 

       return parameters; 
      } 
      else 
      { 
       return null; 
      } 
     } 

     public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod) 
     { 
      Mock.Get(request) 
       .Expect(req => req.HttpMethod) 
       .Returns(httpMethod); 
     } 

     public static void SetupRequestUrl(this HttpRequestBase request, string url) 
     { 
      if (url == null) 
       throw new ArgumentNullException("url"); 

      if (!url.StartsWith("~/")) 
       throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\"."); 

      var mock = Mock.Get(request); 

      mock.Expect(req => req.QueryString) 
       .Returns(GetQueryStringParameters(url)); 
      mock.Expect(req => req.AppRelativeCurrentExecutionFilePath) 
       .Returns(GetUrlFileName(url)); 
      mock.Expect(req => req.PathInfo) 
       .Returns(string.Empty); 
     } 
+1

Modification des cadres moqueurs n'est pas répondre. –

+3

Mais il a aussi fourni une réponse. – usr

+1

+1: Merci d'avoir posté le code. –

3

[Dislaimer: Je travaille à Typemock]

Je sais que ce n'est pas ce que vous avez demandé, mais en regardant les réponses ci-dessus, je dois montrer une autre façon de faire ce que vous avez besoin - en utilisant Isolator:

var fakeId = Isolate.Fake.Instance<IIdentity>(); 
Isolate.WhenCalled(() => fakeId.AuthenticationType).WillReturn("Windows"); 
Isolate.WhenCalled(() => fakeId.Name).WillReturn("TEST_USER"); 
Isolate.WhenCalled(() => fakeId.IsAuthenticated).WillReturn(true); 

var fakePrincipal = Isolate.Fake.Instance<IPrincipal>(); 
Isolate.WhenCalled(() => fakePrincipal.Identity).WillReturn(fakeId); 

var fakeContext = Isolate.Fake.Instance<HttpContext>(); 
Isolate.WhenCalled(() => fakeContext.User).WillReturn(fakePrincipal); 
Questions connexes