Thursday, March 1, 2012

I love TELERIK JUSTMOCK and ASP.NET MVC

I am working on ASP.NET MVC3 project and using different mocking and testing tools such as Nunit,Moq, Telerik JustMock, MVcContrib, and Rhino.

I love commercial version of Telerik JustMock just because of partial method mocking feature. You can test one method and mock other calls within that class,so you can have unit tests for each method.

I have a helper class to build HttpContext. You may need that to check viewresults, session and similar data. These simple examples will show arrange, assert, and partial method mocking.



   1:     public class HttpContextTelerikMock
   2:      {
   3:   
   4:   
   5:   
   6:          public HttpContextBase MockContext { get; set; }
   7:          public HttpRequestBase MockRequest { get; set; }
   8:          public HttpResponseBase MockResponse { get; set; }
   9:          public HttpSessionStateBase MockSession { get; set; }
  10:          public HttpServerUtilityBase MockServer { get; set; }
  11:          public IPrincipal MockUser { get; set; }
  12:          public IIdentity MockIdentity { get; set; }
  13:   
  14:      
  15:          public HttpContextTelerikMock()
  16:          {
  17:              //do nothing
  18:          }
  19:          
  20:          public void SetupSessionOnly(Dictionary<string, string> sessionStubs )
  21:          {
  22:   
  23:              MockContext = Mock.Create<HttpContextBase>();
  24:              foreach (KeyValuePair<string, string> keyValuePair in sessionStubs)
  25:              {
  26:                  Mock.Arrange(() => MockContext.Session[keyValuePair.Key]).Returns(keyValuePair.Value);
  27:   
  28:              }
  29:          }
  30:   
  31:          /// <summary>
  32:          /// Basic mocks for response, request,session, and server
  33:          /// </summary>
  34:          public void BareInit()
  35:          {
  36:              MockContext =   Mock.Create<HttpContextBase>();
  37:              MockRequest = Mock.Create<HttpRequestBase>();
  38:              MockResponse = Mock.Create<HttpResponseBase>();
  39:              MockSession = Mock.Create<HttpSessionStateBase>();
  40:              MockServer = Mock.Create<HttpServerUtilityBase>();
  41:   
  42:   
  43:              Mock.Arrange(()=> MockContext.Request).Returns(MockRequest);
  44:              Mock.Arrange(()=> MockContext.Response).Returns(MockResponse);
  45:              Mock.Arrange(()=> MockContext.Session).Returns(MockSession);
  46:              Mock.Arrange(()=> MockContext.Server).Returns(MockServer);
  47:              
  48:          }
  49:   
  50:          public HttpContextBase SetupCurrentUser(string username)
  51:          {
  52:              //Context.User
  53:              MockContext =   Mock.Create<HttpContextBase>();
  54:              MockRequest = Mock.Create<HttpRequestBase>();
  55:              MockResponse = Mock.Create<HttpResponseBase>();
  56:              var MockUser = Mock.Create<IPrincipal>();
  57:              var MockIdentity = Mock.Create<IIdentity>();
  58:              Mock.Arrange(()=> MockContext.User).Returns(MockUser);
  59:              Mock.Arrange(()=> MockUser.Identity).Returns(MockIdentity);
  60:              Mock.Arrange(()=> MockUser.Identity.Name).Returns(username);
  61:              
  62:              //Request
  63:              Mock.Arrange(()=> MockRequest.InputStream).Returns(new MemoryStream());
  64:   
  65:              //Response
  66:              Mock.Arrange(()=> MockResponse.OutputStream).Returns(new MemoryStream());
  67:              return MockContext;
  68:          }
  69:      }

You can extend this to arrange httpcontext for different requirements.

In this simple example, I want to arrange a another method inside this controller to return a specific response,so i can test single method not all the related calls.

I have interfaces for Repositories to mock their behavior. In this example, "setupRepo" will be a mock object to prevent direct database call in the controller. Our goal is to test only this specific method not all related calls.


   1:          public IBillerSetupRepo setupRepo;  
   2:           //
   3:          // GET: /Default1/Edit/5
   4:          public ActionResult Edit(Guid id)
   5:          {
   6:              string username = User.Identity.Name;
   7:              if (HasAccessToBiller(username, id))
   8:              {
   9:                  Biller biller = setupRepo.GetBiller(id);
  10:                  return View(biller.ToModelView());
  11:              }
  12:              else
  13:              {
  14:                  return View("NotAuthorized");
  15:              }
  16:              
  17:          }

We are returning two different views: notauthorized and edit with model. First test checks the unauthorized view. It will return this view, if user does not have access to this biller.


   1:     [Test]
   2:          public void Edit_SendNotAuthorized()
   3:          {
   4:              BillerController target= new BillerController();
   5:              Guid billerid = Guid.NewGuid();
   6:              string username = "Test234";
   7:              //partial method mock
   8:              Mock.Arrange(() => target.HasAccessToBiller(username, billerid)).Returns(false);
   9:   
  10:              //context adjustment
  11:              HttpContextTelerikMock helper = new HttpContextTelerikMock();
  12:              target.ControllerContext = new ControllerContext(helper.SetupCurrentUser(username), new RouteData(), target);
  13:   
  14:              //Check viewpage
  15:              ViewResult result = target.Edit(billerid) as ViewResult;
  16:              Assert.AreEqual("NotAuthorized", result.ViewName);
  17:   
  18:   
  19:          }

Second call will check the call, if user has access to this biller:


   1:     [Test]
   2:          public void Edit_HasAccess_SendModelTOView()
   3:          {
   4:              IBillerSetupRepo mocksetuprepo = Mock.Create<IBillerSetupRepo>();
   5:              BillerController target = new BillerController();
   6:              Guid billerid = Guid.NewGuid();
   7:              string username = "Test234";
   8:              Biller testbiller = new Biller
   9:                                      {
  10:                                          BillerName = "Testbiller2xbv342342"
  11:                                      };
  12:              //partial method mock
  13:              Mock.Arrange(() => target.HasAccessToBiller(username, billerid)).Returns(true);
  14:              //Arrange repo to return our model
  15:              Mock.Arrange(() => mocksetuprepo.GetBiller(billerid)).Returns(testbiller);
  16:              HttpContextTelerikMock helper = new HttpContextTelerikMock();
  17:              target.ControllerContext = new ControllerContext(helper.SetupCurrentUser(username), new RouteData(), target);
  18:              target.setupRepo = mocksetuprepo;
  19:   
  20:   
  21:              ViewResult result = target.Edit(billerid) as ViewResult;
  22:              Assert.AreEqual(testbiller.BillerName, ((BillerView)result.Model).BillerName);
  23:              //Assert that mock object was called
  24:              Mock.Assert(() => mocksetuprepo.GetBiller(billerid), Occurs.Once());
  25:              
  26:          }

No comments:

Post a Comment

Hey!
Let me know what you think?