Automate web service testing, Part 2: Test a web service with XMLUnit

Learn an automation technique using the IBM Rational Software Architect development platform

This tutorial series, developed for testers and developers who are interested in functional web service testing, walks you through automating typical web service testing using technologies, such as JUnit, Apache Commons HttpClient, and Apache XMLUnit. In this installment, Part 2, you'll learn how to create a simple web service, how to use HttpClient to invoke a web service, and how to compare the expected response and actual response using XMLUnit. The authors demonstrate these techniques on the IBM® Rational® Software Architect development platform.

Share:

Mohan Jadhav (mohan.jadhav@in.ibm.com), Staff Software Engineer, IBM India Software Labs, Bangalore

Mohan Jadhav photoMohan K Jadhav is a staff software engineer with IBM India Software Labs, Bangalore. He is currently working on RFID offerings from IBM and has expertise in automation testing and design.


developerWorks Contributing author
        level

Mansoor Ahmed, Software Engineer, IBM Software Labs, Bangalore

Mansoor Ahmed photoMansoor Ahmed is a software engineer with IBM India Software Labs, Bangalore. He is currently working on WebSphere Messaging and Data Services, a telecom product, and has expertise in Web services and open source development.



23 March 2007

Also available in Chinese Spanish

Before you start

About this series

Web services are increasingly becoming key components in business applications, and with the emergence of paradigms such as Service-Oriented Architecture (SOA), the focus on web services continues to grow. In these service-oriented and service-critical applications, web service testing assumes equal significance. Rapid creation and deployment of complex web services offers a challenge to the QA team. Automating web service testing can help the team manage the effort efficiently.

Web service testing typically includes the following tasks:

  1. Generate the client or skeleton code for the web service.
  2. Define the test inputs.
  3. Invoke the web service using the client or skeleton code.
  4. Verify that the actual response is similar to that of the expected response.

Of those activities, client or skeleton code generation and response verification require the most effort.

Various tools are available to generate the client or skeleton code for a web service based on its WSDL file; however, the code generated might be proprietary and might need to be regenerated every time the WSDL changes. A solution to this problem is to eliminate the generation of the client or skeleton code and invoke the web service directly through a generic HTTP client. Later in the series, you'll see one such toolkit provided by Apache Commons HttpClient (hereafter referred to as HttpClient) API.

Similarly, response verification usually involves some kind of manual intervention, depending on the complexity of the response content. If the response contains simple elements, verification can be simple, since it requires you to just check the value in the simple element. For responses that contain complex elements and a huge list of such complex elements, manual verification can require much more effort.

This series introduces you to a technique to automate the testing of a typical web service using an array of technologies, such as JUnit, HttpClient, and Apache XMLUnit (hereafter referred to as XMLUnit). The technique is demonstrated on the development platform offered by IBM Rational Software Architect.

This series has three parts:

  • Part 1 demonstrated how to create a simple web service with IBM Rational Software Architect.
  • Part 2 introduces the XMLUnit, which offers the API to compare two files in XML form.
  • Part 3 tests a secured web service with IBM Rational Software Architect and XMLUnit

About this tutorial

In this second tutorial in the series, you'll create a simple web service, use HttpClient to invoke a web service, and compare the expected response and actual response using XMLUnit -- all on the IBM Rational Software Architect development platform.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of the web service and its development in Java, and have some exposure to unit testing tools, such as JUnit.

System requirements

You need the following software to complete this tutorial:


Define the input and output

In Part 1 of this series, you created a sample web service that returned a list of users. Now you'll specify the request and expected response to the web service.

Request

Typically, the request to the web service is in SOAP format. For the sample web service, for instance, the request will look like Listing 1.

In Listing 1, the getUsers() method is invoked on the web service. The text above the method constitutes the SOAP header. You also might want to attach a customized header in your request.

Listing 1. Request to the web service
<?xml version="1.0" encoding="UTF-8" ?> 
<SOAP-ENV:Envelope 
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:q0="http://sample.ws.ibm.com" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
  <q0:getUsers/> 
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Now save this request in an XML file, such as C:\wssample\request.xml.

Expected response

The expected response for your sample web service is the user list in Listing 2.

Listing 2. List of users
<?xml version="1.0" encoding="UTF-8" ?> 
<SOAP-ENV:Envelope 
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:q0="http://sample.ws.ibm.com" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  
  <SOAP-ENV:Body>
    <getUsersReturn>  
      <User>  
        <name>John</name>   
        <address>    
          <street>Park Street</street>     
          <city>Washington</city>     
          <zip>012345</zip>     
        </address>    
      </User>  
      <User>    
        <name>Mohan</name>   
        <address>    
          <street>Avenue Street</street>     
          <city>Bangalore</city>     
          <zip>456789</zip>     
        </address>    
      </User>  
      <User>    
        <name>Mansoor</name>   
        <address>    
          <street>Martin Street</street>     
          <city>Bangalore</city>     
          <zip>135791</zip>     
        </address>    
      </User>    
    </getUsersReturn>      
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In the Listing 2, getUsersReturn is the response's root element. It ignores the SOAP header. Save this expected response in an XML file, such as C:\wssample\expected_response.xml.

Write the invocation client for the web service

Now you've defined and stored the web service's input and output test data in the disk. Next you'll write the client code to invoke the web service using the HttpClient API:

  1. Open Rational Software Architect, and click Menu > Window > Open Perspective > Java.
  2. Go to File > New > Project... > Java Project , as Figure 1 shows.
    Figure 1. New project
    Figure 1
  3. As Figure 2 shows, enter a project name, such as SampleTestProject, and click Next.
    Figure 2. Create a Java project
    Figure 2
  4. In the Java Settings page, click SampleTestProject, and then click the Add Folder button.
  5. Enter src as the source folder name, and click OK, as Figure 3 shows.
    Figure 3. Java Settings page
    Figure 3
  6. The wizard asks Do you want to remove the project as source folder and update build output folder to 'SampleTestProject/bin'? (see Figure 4). Choose Yes.
    Figure 4. New source folder
    Figure 4
  7. Click Finish. The project view should look like Figure 5.
    Figure 5. View of the Java project
    Figure 5
  8. Now, create a package in the src folder, such as com.ibm.ws.sample.test. This package will contain your test code.
  9. Create a folder called lib under the SampleTestProject by right-clicking SampleTestProject and selecting New > Folder.
  10. Add the .jar files commons-codec-1.3.jar, commons-logging.jar, and commons-httpclient-3.0.1.jar to the lib folder.
  11. Add the .jar files to the project build path by right-clicking the project and selecting Properties.
  12. Select Java Build Path in the left pane, then select the Libraries tab on the right, as Figure 6 shows.
    Figure 6. Properties for SampleTestProject
    Figure 6
  13. Click the Add JARs... button. Then select the .jar files in the lib folder, and click OK, as Figure 7 shows.
    Figure 7. JAR selection
    Figure 7
  14. Click OK in the Properties page.
  15. Now, create a Java class called SampleHttpClient.java in the package com.ibm.ws.sample.test, as Listing 3 shows.
    Listing 3. Create a Java class
    package com.ibm.ws.sample.test;
    
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.methods.PostMethod;
    import org.apache.commons.httpclient.methods.RequestEntity;
    import org.apache.commons.httpclient.methods.StringRequestEntity;
    
    public class SampleHttpClient 
    {  
      public static String invokeWebService(String webServiceURL, 
        String  requestXMLPath) 
      throws FileNotFoundException, Exception  
      {    
        PostMethod post = null;    
        HttpClient client = new HttpClient();    
        
        try     
        {      
          // Read the SOAP request from the file      
          StringBuffer requestFileContents = new StringBuffer();      
          BufferedReader bufferedReader = new BufferedReader
          (new FileReader(requestXMLPath));      
          String line = null;		      
          
          while((line = bufferedReader.readLine()) != null)      
          {        
            requestFileContents.append(line);      
          }      
          
          post = new PostMethod(webServiceURL);      
          post.setRequestHeader("Accept","application/soap+xml,application/
          dime,multipart/related,text/*");      
          post.setRequestHeader("SOAPAction", "");            
          
          // Request content will be retrieved directly from the input stream      
          RequestEntity entity = new StringRequestEntity(requestFileContents
          .toString(), "text/xml",  "utf-8");      
          post.setRequestEntity(entity);            
          
          // Returns a number indicating the status of response	          
          int result = client.executeMethod(post);      
          String response = post.getResponseBodyAsString();      
          return response;    
        }     
        
        finally     
        {      
          // Release current connection to the connection pool once you are done      
          post.releaseConnection();     
        }  
      }
    }
  16. Save and build the project.

Invoke the web service from a JUnit test

In the previous section, you created a simple HttpClient that would invoke the web service with a given request. In this section, you'll create a JUnit test that uses this client.

  1. Right-click the package com.ibm.ws.sample.test, and add a new JUnit test, such as SampleTest, by selecting New > Other... > Java > JUnit > JUnit Test Case.
  2. Create the test method shown in Listing 4.
  3. Save and build the project.
  4. Right-click SampleTest.java, and run as JUnit. You'll see the response from the web service printed to the console.
Listing 4. Test method
package com.ibm.ws.sample.test;
  
import java.io.FileNotFoundException;
import junit.framework.TestCase;
  
public class SampleTest extends TestCase 
{  
 public void test() throws FileNotFoundException, Exception  
 {    
   // Web service URL    
   final String wsURL = "http://localhost:9080/SampleProject/services/Users";
      
   // Request XML path    
   final String requestXMLPath = "C:/wssample/request.xml";    
      
   // Invoke the Web service    
   String webServiceResponse = SampleHttpClient.invokeWebService(wsURL,requestXMLPath);
   System.out.println("Response: " + webServiceResponse);    
 }
}

Verify the test using XMLUnit

In the previous section, you created a JUnit test to invoke the web service and get the response. Now you'll modify the JUnit test to store the actual response from the web service into a file and then compare it with the expected response using the XMLUnit API.

  1. Add xmlunit1.0.jar to the project build path.
  2. Modify the JUnit test method by adding the code in blue to the code shown in Listing 5.







    Listing 5. Compare responses
      package com.ibm.ws.sample.test;
      
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      import java.io.FileOutputStream;
      import java.io.InputStreamReader;
      import java.io.OutputStreamWriter;
      import java.io.Reader;
      import junit.framework.TestCase;
      import org.custommonkey.xmlunit.Diff;
      import org.custommonkey.xmlunit.XMLAssert;
      import org.custommonkey.xmlunit.XMLUnit;
      
      public class SampleTest extends TestCase 
      {  
        public void test() throws FileNotFoundException, Exception  
        {    
          // Web service URL    
          final String wsURL = "http://localhost:9080/
          SampleProject/services/Users";		    
          
          // Request XML path    
          final String requestXMLPath = "C:/wssample/request.xml";      
          
          // Expected response path    
          final String expectedXMLPath = 
            "C:/wssample/expected_response.xml";		    
          
          // Actual response path    
          final String actualXMLPath = "C:/wssample/actual_response.xml";	    
          
          // Encoding     
          final String encoding = "UTF-8";		    
          
          // Invoke the web service    
          String webServiceResponse = SampleHttpClient.invokeWebService
          (wsURL,requestXMLPath);
          
          // Store the response in the disk    
          File responseFile = new File(actualXMLPath);    
          responseFile.createNewFile();    
          OutputStreamWriter oSW = new OutputStreamWriter
          (new FileOutputStream(responseFile),encoding); 
          oSW.write(webServiceResponse);	    
          oSW.flush();    
          oSW.close();    
          
          // Compare the responses    
          Reader expectedXMLReader = new InputStreamReader
          (new FileInputStream(expectedXMLPath), encoding);    
          Reader actualXMLReader = new InputStreamReader
          (new FileInputStream(actualXMLPath), encoding);    
          
          // Ignore the white space while comparing    
          XMLUnit.setIgnoreWhitespace(true);		    
          
          // Diff object, which contains the differences, if any    
          Diff xmlDiff = new Diff(expectedXMLReader, actualXMLReader);		    
          
          // "false" ignores the order of the users in the XMLs    
          XMLAssert.assertXMLEqual(xmlDiff,false);  
        }
    }
  3. Save and build the project.
  4. Right-click SampleTest.java, and run as JUnit.
  5. The JUnit console appears in green, indicating that the test passed, as Figure 8 shows.
    Figure 8. JUnit console
    Figure 8
  6. Now change the user order in the expected response and rerun the test. Open the expected response XML in C:\wssample\expected_response.xml.
  7. Change the user order, as Listing 6 shows.
    Listing 6. New user order
      <?xml version="1.0" encoding="UTF-8" ?>
      <SOAP-ENV:Envelope 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:q0="http://sample.ws.ibm.com" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        
        <SOAP-ENV:Body>
          <getUsersReturn>  
          <User>    
            <name>Mohan</name>   
            <address>    
              <street>Avenue Street</street>     
              <city>Bangalore</city>     
              <zip>456789</zip>     
            </address>    
          </User>  
          <User>    
            <name>Mansoor</name>   
            <address>    
              <street>Martin Street</street>     
              <city>Bangalore</city>     
              <zip>135791</zip>     
            </address>    
          </User>  
          <User>  
            <name>John</name>   
            <address>    
              <street>Park Street</street>     
              <city>Washington</city>     
              <zip>012345</zip>     
            </address>    
          </User>    
          </getUsersReturn>      
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
  8. Save the file, and rerun the test. It should pass again.

Conclusion

In this tutorial, you learned a technique to automate the testing of web service output using HttpClient and XMLUnit APIs. Specifically, you learned how to:

  • Create a simple web service.
  • Use HttpClient to invoke a web service.
  • Compare the expected response and actual response using XMLUnit.

Resources

Learn

Get products and technologies

  • Innovate your next development project with IBM trial software, available for download or on DVD.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services, Open source
ArticleID=204111
ArticleTitle=Automate web service testing, Part 2: Test a web service with XMLUnit
publish-date=03232007