OWASP O2 Platform Blog

Unit Test for HttpModule using Moq to wrap HttpRequest

Using the Mocking HttpContext HttpRequest and HttpResponse for UnitTests (using Moq) API, here is a unit test that uses it to test if a method used inside an HttpModule is doing the right thing (in this case the HttpModule will set up the current HttpContext User’s roles to a mapping that is created from a summited token/Guid)

This script is done as an NUnit Test: 

[Test]
        public string TestSoapRequestUtils()
        {                   

first create out mock objects and do a basic test (i.e. write and read some text into the HttpRequest

            //**** testing SoapRequestUtils.GetPostDataAsXmlDocument
            var mockHttpContext = new API_Moq_HttpContext();       
            var httpContext = mockHttpContext.httpContext();               
            var requestText = "this is some text in Xml Format";
            httpContext.request_Write(requestText.serialize(false));
            var xmlDocument = SoapRequestUtils.GetPostDataAsXmlDocument(httpContext);
            Assert.That(xmlDocument.notNull());
            Assert.That(xmlDocument.OuterXml.contains(requestText), "requestText was not in the generated Xml string");

Now lets do a test where we submit a soap request and validate that the function that extracts a value is working as expected


            //**** testing SoapRequestUtils.GetPostDataElementValue
            var adminSessionID = "503d4cc3-be37-42ca-961b-8ee11e4f96eb";
            var soapRequest = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
                              "<soap:Envelope xmlns:soap=\"<a href="http://schemas.xmlsoap.org/soap/envelope/\">http://schemas.xmlsoap.org/soap/envelope/\</a>" xmlns:xsi=\"<a href="http://www.w3.org/2001/XMLSchema-instance\">http://www.w3.org/2001/XMLSchema-instance\</a>" xmlns:xsd=\"<a href="http://www.w3.org/2001/XMLSchema\">http://www.w3.org/2001/XMLSchema\</a>">"+
                              "    <soap:Body>"+
                              "        <GetUserInformation xmlns=\"<a href="https://TeamMentor.securityinnovation.com:13415/\">https://TeamMentor.securityinnovation.com:13415/\</a>">"+
                              "            <AdminSessionID>{0}</AdminSessionID>".format(adminSessionID) +
                              "            <UserID>202</UserID>"+
                              "        </GetUserInformation>"+
                              "    </soap:Body>"+
                              "</soap:Envelope>";                             
                             
            mockHttpContext.request_Write_Clear()
                           .request_Write(soapRequest);                                                  
            Assert.That(adminSessionID ==  httpContext.GetPostDataElementValue("AdminSessionID") , "fetched adminSessionID didn't match");

The next tests checks that the roles in httpContext.User have been correcly set

            //**** testing RoleBaseSecurity.SetCurrentUserRoles
            var roles = (string[])httpContext.SetCurrentUserRoles(UserRole.Admin, UserRole.ManageUsers).field("m_roles");
           
            Assert.That(roles.size()==2 && roles[0] == "Admin" && roles[1]=="ManageUsers", "in SetCurrentUserRoles, m_roles did not had the right value");
           
            //**** testing UserRoleBaseSecurity.MapRolesBasedOnSessionGuid
            var sessionIdGuid = this.getGuidOfLoggedInUser();
           
            HttpContextFactory.Context = httpContext;       
            var userRole = sessionIdGuid.userType();
           
            new UserRoleBaseSecurity().MapRolesBasedOnSessionGuid(sessionIdGuid); 
            roles = (string[])System.Threading.Thread.CurrentPrincipal.field("m_roles");
           
            Assert.That(roles.size() == 3 && roles[0] == userRole.str(), "in MapRolesBasedOnSessionGuid, m_roles did not had the right value"); 

If all tests passed, return a message to the O2 Unit Test execution GUI

                        
            return "ok: TestSoapRequestUtils";
           
        }

April 10, 2011 Posted by | Moq | 1 Comment

Mocking HttpContext HttpRequest and HttpResponse for UnitTests (using Moq)

I just added support to O2 Platform for easy mocking of HttpContext, HttpRequest and HttpResponse (very useful for ASP.NET Unit Test and Security Scripting). 

The solution is based on the Moq Mocking framework and on the great info provided in this , this and this posts

As an example, this is how the Input Stream of the HttpRequest can be maniplated (same logic for the OutputStream):

var mockHttpContext = new API_Moq_HttpContext();
       
var httpContext = mockHttpContext.httpContext();


httpContext.request_Write("<html><body>".line()); 
httpContext.request_Write("   this is a web page".line());  
httpContext.request_Write("</body></html>"); 

return httpContext.request_Read();

The API_Moq_HttpContext class is the one that implements the Mocking infrastructure

public class API_Moq_HttpContext
    {           
        public Mock<HttpContextBase> MockContext { get; set; }
        public Mock<HttpRequestBase> MockRequest { get; set; }
        public Mock<HttpResponseBase> MockResponse { get; set; }
        public Mock<HttpSessionStateBase> MockSession { get; set; }
        public Mock<HttpServerUtilityBase> MockServer { get; set; }
        public Mock<IPrincipal> MockUser { get; set; }
        public Mock<IIdentity> MockIdentity { get; set; }
       
        public HttpContextBase HttpContextBase  { get; set; }
        public HttpRequestBase HttpRequestBase  { get; set; }
        public HttpResponseBase HttpResponseBase  { get; set; }       
       
        public API_Moq_HttpContext()
        {
            createBaseMocks();
            setupNormalRequestValues();
        }
       
        public API_Moq_HttpContext createBaseMocks()
        {
            MockContext = new Mock<HttpContextBase>();
            MockRequest = new Mock<HttpRequestBase>();
            MockResponse = new Mock<HttpResponseBase>();
            MockSession = new Mock<HttpSessionStateBase>();
            MockServer = new Mock<HttpServerUtilityBase>();
           
   
            MockContext.Setup(ctx => ctx.Request).Returns(MockRequest.Object);
            MockContext.Setup(ctx => ctx.Response).Returns(MockResponse.Object);
            MockContext.Setup(ctx => ctx.Session).Returns(MockSession.Object);
            MockContext.Setup(ctx => ctx.Server).Returns(MockServer.Object);
            
            
             HttpContextBase = MockContext.Object;
             HttpRequestBase = MockRequest.Object;
             HttpResponseBase = MockResponse.Object;
                         
             return this;
        }
       
        public API_Moq_HttpContext setupNormalRequestValues()
        {
            //Context.User
            var MockUser = new Mock<IPrincipal>();
            var MockIdentity = new Mock<IIdentity>();       
            MockContext.Setup(context => context.User).Returns(MockUser.Object);
             MockUser.Setup(context => context.Identity).Returns(MockIdentity.Object);
            
             //Request
             MockRequest.Setup(request =>request.InputStream).Returns(new MemoryStream());
            
             //Response
             MockResponse.Setup(response =>response.OutputStream).Returns(new MemoryStream());
             return this;
        }
    }

 

At the moment it has a couple extension methods to help writing and reading data from the HttpRequest InputStream and HttpResponse OutputStream

    public static class API_Moq_HttpContext_ExtensionMethods
    {
        public static HttpContextBase httpContext(this API_Moq_HttpContext moqHttpContext)
        {
            return moqHttpContext.HttpContextBase;
        }
       
        public static HttpContextBase request_Write(this HttpContextBase httpContextBase,string text)
        {                                                       
            httpContextBase.stream_Write(httpContextBase.Request.InputStream, text);           
            return httpContextBase;
        }
       
        public static string request_Read(this HttpContextBase httpContextBase)
        {                   
            return httpContextBase.stream_Read(httpContextBase.Request.InputStream);
        }
       
        public static HttpContextBase response_Write(this HttpContextBase httpContextBase,string text)
        {                                                       
            httpContextBase.stream_Write(httpContextBase.Response.OutputStream, text);           
            return httpContextBase;
        }
       
        public static string response_Read(this HttpContextBase httpContextBase)
        {                   
            return httpContextBase.stream_Read(httpContextBase.Response.OutputStream);                       
        }
       
        public static HttpContextBase stream_Write(this HttpContextBase httpContextBase, Stream inputStream, string text)
        {                                                       
            var streamWriter = new StreamWriter(inputStream);
           
            inputStream.Position = inputStream.property("Length").str().toInt();
            streamWriter.Write(text);   
            streamWriter.Flush();            
            inputStream.Position = 0;            
           
            return httpContextBase;
        }
       
        public static string stream_Read(this HttpContextBase httpContextBase, Stream inputStream)
        {                               
            var originalPosition = inputStream.Position;
            var streamReader = new StreamReader(inputStream);
            var requestData = streamReader.ReadToEnd();   
            inputStream.Position = originalPosition;
            return requestData;
        }
    }

April 5, 2011 Posted by | Moq | 6 Comments