Click here to Skip to main content
15,885,757 members
Articles / Desktop Programming / Windows Forms
Article

Web services testing tool with hierarchical type parsing

Rate me:
Please Sign up or sign in to vote.
3.22/5 (3 votes)
17 Jul 20073 min read 32.8K   644   20   12
An article on building a tool, helping to test web services with hierarchical input/output types

Screenshot - WebServiceGenericTool.jpg

Introduction

The aim of the tool presented in this article is to increase the productivity of webservices testing. There are plenty of tools available for testing web services, from open source -- like Windows Forms web service clients using ServiceDescriptionImporter -- to such monsters as XMLSpy. Yet searching the web, I couldn't find a tool that would allow for quick testing of a webservice having a complicated XML hierarchy -- i.e. not primitive types -- as input. It would be great if such a tool would allow a tester unfamiliar with the details of XML namespaces and SOAP protocol to simply test the business logic of the web service itself, without thinking about the details of XML serialization.

Using the code

The core of this tool is its use of reflection to iterate through types, generated by ServiceDescriptionImporter after it imports WSDL file. It populates the Windows Forms TreeView with a hierarchy of input from a selected web service operation, i.e. a proxy class method. Although this could seem like an easy task, I've faced a number of challenges when trying to build a working solution:

  • It should be possible to edit "writable" nodes, like text, in the hierarchy. This would actually edit the property of some object, which in turn might be a property of some other parent object
  • Although TreeView would list a full hierarchy of input objects, only some properties and sub-properties need to be "enabled" in different test scenarios, i.e. TreeView with checkboxes
  • Some of the properties in the hierarchy can be arrays of objects, adding complexity to populating these properties with values. There is also a variable number of items that could populate the array

The are 2 main classes that this tool uses to achieve its goals: WebServTreeNode and WSDLImporter. WSDLImporter contains static methods for importing of WSDL and parsing resulting objects. WebServTreeNode is an extension of System.Windows.Forms.TreeNode; it is used to store and populate the objects and their container objects. To make parsing of the object easier, the process was divided between 2 methods. parseWebParamType initially parses the object, which could be an array. parseWebParamProps parses the properties of non-array objects.

C#
private static void parseWebParamType(object pObject, 
    WebServTreeNode pNode, PropertyInfo pPropInfo, Array pParentArray)
{
    Type tObjectType = 
        (pParentArray != null) ? 
        pParentArray.GetType() : tObjectType = pObject.GetType();

    if (tObjectType.IsArray)
    {
        tObjectType = tObjectType.GetElementType();

        if (tObjectType.IsArray)
            throw new NotSupportedException(
            NotSupportedExceptionType.MultiDimArrays);

        object oNewContainerObject = Helper.invokeConstructor(tObjectType);

        if (pParentArray != null)
            pParentArray.SetValue(oNewContainerObject, 0);

        WebServTreeNode nNewNode = 
            new WebServTreeNode(String.Format("{0}[]", 
            tObjectType.Name), WebServTreeNodeType.ArrayElement, null, null);

        nNewNode.ArrayObject = pParentArray;
        nNewNode.ArrayIndex = 0;
        pNode.Nodes.Add(nNewNode);
        nNewNode.ValueType = tObjectType;
        nNewNode.Value = oNewContainerObject;

        parseWebParamProps(oNewContainerObject, nNewNode);

    }
    else
    {
        parseWebParamProps(pObject, pNode);
    }

}

private static void parseWebParamProps(object pObject, WebServTreeNode pNode)
{
    Type tObjectType = pObject.GetType();

    //// looping through props
    foreach (PropertyInfo pi in tObjectType.GetProperties())
    {
        WebServTreeNodeType propNodeType = WebServTreeNodeType.Element;
        if (!Helper.isTypeWritable(pi.PropertyType))
        {
            if (pi.PropertyType.IsArray)
                propNodeType = WebServTreeNodeType.Array;
            else
               propNodeType = WebServTreeNodeType.Container;
        }

        WebServTreeNode nNewNode = 
            new WebServTreeNode(pi.Name, propNodeType, pObject, pi);
        pNode.Nodes.Add(nNewNode);

        if (propNodeType == WebServTreeNodeType.Container || 
            propNodeType == WebServTreeNodeType.Array)
        {
            object oNewPropObject = null;
            Array oNewPropArrayObject = null;

            if (propNodeType == WebServTreeNodeType.Array)
            {
               if (pi.PropertyType.GetElementType().IsArray)
                   throw new NotSupportedException(
                   NotSupportedExceptionType.MultiDimArrays);
               oNewPropArrayObject = 
                   Array.CreateInstance(pi.PropertyType.GetElementType(), 1);
            }
            else
                oNewPropObject = Helper.invokeConstructor(pi.PropertyType);

                nNewNode.Value = 
                    (oNewPropArrayObject != null) ? 
                    oNewPropArrayObject : oNewPropObject;
                parseWebParamType(oNewPropObject, 
                    nNewNode, pi, oNewPropArrayObject);
        }
        else
        {
            nNewNode.ValueType = pi.PropertyType;
            nNewNode.Value = Helper.invokeConstructor(pi.PropertyType);
        }
    }
    //// looping through props
}

As you can see, the main task of these methods is to create instances of WebServTreeNode of appropriate type --i.e. WebServTreeNodeType enumeration -- and populate it with references to the object it should populate. The logic of editing properties of the objects as well as "cloning" array element nodes is placed within methods and properties of WebServTreeNode, which proved to be quite a reasonable design decision.

Points of interest

Although the functionality of the tool is all about web services, the "core" of its source code is all about reflection. Object parsing code is not the most effective. It still has some bugs and "scenarios" it does not support, but it was a great exercise in object-orientation, allowing a beginner to learn the intricacies of .NET object structure. Plus, it already proved to be a great helper in testing my current project's webservices. On the other hand, I hope that this tool will prove to be interesting -- at least as idea, if not its source code -- for webservices developers who are interested in .NET and are searching for a way to unit-test webservices. I think that the main part of the source code is clean enough to be easily extendable for new webservice testing scenarios.

History

  • 17 June, 2007 -- Original version posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Latvia Latvia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralNeed Help Pin
mdeepakus2-Oct-08 4:56
mdeepakus2-Oct-08 4:56 
GeneralRe: Need Help Pin
Konstantin Onufrijev2-Oct-08 5:17
Konstantin Onufrijev2-Oct-08 5:17 
GeneralRe: Need Help Pin
mdeepakus2-Oct-08 22:15
mdeepakus2-Oct-08 22:15 
I have a web service which is wse3.0 enabled. Now when ever I try to test that service its give error (0, 9). I have tried to implement the wse in the tool you have provided by enabling WSE and adding the wse config file but for setting user token I need to make the proxy and then I can set the credentials.

Could to please suggest me if it’s possible? I have tried this but as I am using proxy object to set the credentials and wsdl (Reflection) to call the function it’s give the same error.

Thanks,
Deepak M.
GeneralRe: Need Help Pin
Konstantin Onufrijev2-Oct-08 23:20
Konstantin Onufrijev2-Oct-08 23:20 
GeneralRe: Need Help Pin
mdeepakus3-Oct-08 1:34
mdeepakus3-Oct-08 1:34 
GeneralIdea Pin
vvvv6614-Aug-08 2:53
vvvv6614-Aug-08 2:53 
GeneralError Pin
lustuyck10-Aug-08 23:49
lustuyck10-Aug-08 23:49 
GeneralRe: Error Pin
Konstantin Onufrijev11-Aug-08 0:02
Konstantin Onufrijev11-Aug-08 0:02 
GeneralRe: Error Pin
lustuyck12-Aug-08 2:53
lustuyck12-Aug-08 2:53 
Generalcredentials question Pin
picazo21-Dec-07 6:23
picazo21-Dec-07 6:23 
AnswerRe: credentials question Pin
Konstantin Onufrijev29-Jul-08 10:35
Konstantin Onufrijev29-Jul-08 10:35 
GeneralThanks. Pin
Michael Sync17-Jul-07 21:10
Michael Sync17-Jul-07 21:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.