SIGN UP MEMBER LOGIN:    
ARTICLE

Test-driven development approach for WCF Web services

Posted by John Charles Olamendy Articles | Testing April 11, 2009
In this article, I will show how programmers can use the test-driven development approach to implement and test Web service solutions.
Reader Level:

Introduction

This is the third article of series of articles related to Test-driven development (TDD) approach in Microsoft.NET. My intention is to illustrate this approach with several real-world examples.

In this article, I will show how programmers can use the test-driven development approach to implement and test Web service solutions.

Getting started with the Web service solution

As an illustrative example, we're going to develop a Calculator Web service which is being called from a console application. In order to implement and test the principles of TTD applied to Web service solutions, we're going to create the Web service side as a Console Application project within a solution (see Figure 1).

Figure 1

Now we're going to add a class which implements the Calculator WCF Web service (see Figure 2).

Figure 2

The first step in the test-driven development approach is, of course as its name implies, the formulation of a list of tests. One important thing to keep in mind is that the list of tests is dynamic in order to add or remove tests for testing in different environments.

In this case, the list test case for the Calculator Web service (as illustrative example, just one method to add two integers) is very simple, as follows:

  • Create an instance of a proxy for the Web service and send two integers to be calculated. We're testing that the communication is established and the underlying business logic of the Web service is correct.

In order to implement these test cases, we have to define the interface between the Calculator Web services, the proxy and the test cases. One way that I follow is to specify the interface of the Calculator service and then we reference the interface and call the methods using the proxy for the service.

I like a lot this approach because when we define interfaces for the classes, conceptually we're separating the abstraction layer from the implementation. So, our class instances provide its interfaces as roles and communication mechanisms (independent of the implementation) to external entities which want to communicate to and consume the services. If later we want to change the implementation of the service (to upgrade the services or for possible errors discovered in the test phase); then we make the changes in an agile way without changing the interface and breaking the line with the consumers of the interface services. From the point of view of technology is an advantage too, because, the clients which use our Web service don't need to re-build or change some code due to the interface is stable.

Let's define the ICalculator interface as well as the Calculator class representing the Web service (see Listing 1).

using System;

using System.ServiceModel;

 

namespace TDDWebServiceApp

{

    [ServiceContract()]

    public interface ICalculatorService

    {

        [OperationContract]

        int Add(int nParam1, int nParam2);

    }

 

    public class CalculatorService : ICalculatorService

    {

        public int Add(int nParam1, int nParam2)

        {

            throw new Exception("The method or operation is not implemented.");

        }

    }

}

Listing 1

Now let's specify the configuration file with the parameters necessary to run the Web service in its hosting environment (see Listing 2).

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

          <system.serviceModel>

                   <services>

                             <service name="TDDWebServiceApp.CalculatorService" behaviorConfiguration="returnFaults">

                                      <endpoint contract="TDDWebServiceApp.ICalculatorService" binding="wsHttpBinding"/>

                             </service>

                   </services>

                   <behaviors>

                             <serviceBehaviors>

                                      <behavior name="returnFaults" >

                                                <serviceDebug includeExceptionDetailInFaults="true" />

                                                <serviceMetadata httpGetEnabled="true" />

                                      </behavior>

                             </serviceBehaviors>

                   </behaviors>

          </system.serviceModel>

</configuration>

Listing 2

And the code to create the hosting environment which manages the life cycle of the Calculator Web service (see Listing 3).

using System;

using System.Collections.Generic;

using System.Text;

using System.ServiceModel;

 

namespace TDDWebServiceApp

{

    public class Program

    {

        ServiceHost m_objServiceHost = null;

 

        public void StartService()

        {

            Uri baseAddress = new Uri("http://localhost:8888/TDDWebServiceApp/CalculatorService");

            this.m_objServiceHost = new ServiceHost(typeof(CalculatorService), baseAddress);

            this.m_objServiceHost.Open();

        }

 

        public void StopService()

        {

            if (this.m_objServiceHost.State != CommunicationState.Closed)

                this.m_objServiceHost.Close();

        }

 

        static void Main(string[] args)

        {

            Program objProgram = new Program();

            System.Console.WriteLine("Starting the service CalculatorService");

            objProgram.StartService();

            System.Console.WriteLine("Press any key to finish the service ...");

            System.Console.ReadKey();

            objProgram.StopService();

        }

    }

}

Listing 3

Now you can compile and run the Web service.

The first step to test the Calculator Web service is to create the proxy for the service. Let's create Class Library project to include the proxy and the test suite as shown in Figure 3.

Figure 3

In order to create the proxy for the service, you should run the console hosting the service and move to the directory path of the test suite class library and runt he following command (see Listing 4) which automatically creates a config file and a file with the logic of proxy to communicate correctly with the server.

svcutil http://localhost:8888/TDDWebServiceApp/CalculatorService?wsdl

Listing 4

Then, include the generated file in the project add a reference to the System.ServiceModel assembly. You have to add a reference to the NUnit framework (see Figure 4) and a fixture class (see Figure 5).

Figure 4

Figure 5

Now it's time to write code for the test cases using the test method TestCalculator annotated with Test attribute. The test to check if you add two integers and result is correct. It's remarkable to say that these methods must be declared as public, be an instance method (non-static), with return type as void, and take no parameters (see Listing 6).

using System;

using System.Collections.Generic;

using System.Text;

using NUnit.Framework;

 

namespace CalculatorSvcTestSuitePkg

{

    [TestFixture]

    public class CalculatorServiceFixture

    {

        [Test]

        public void TestCalculator()

        {

            CalculatorServiceClient objClient = new CalculatorServiceClient();

            Assert.AreEqual(3, objClient.Add(1,2));

        }

    }

}

Listing 5

Now let's test our business logic and the communication with the CalculatorService Web service. Right-click on the CalculatorSvcTestSuitePkg project and select Properties from the context menu. In the Debug tab, set GUI NUnit test runner (see Figure 6).

Figure 6

Now let's build the solution and run the test. When the GUI NUnit test runner is run for the first time, we need to load the test project (see Figure 7).

Figure 7

If you run the test you receive an exception because we have not implemented the service (see Figure 8).

Figure 8

Now let's go to the service and implement the business logic to later test the service (see Listing 6).

using System;

using System.ServiceModel;

 

namespace TDDWebServiceApp

{

    [ServiceContract()]

    public interface ICalculatorService

    {

        [OperationContract]

        int Add(int nParam1, int nParam2);

    }

 

    public class CalculatorService : ICalculatorService

    {

        public int Add(int nParam1, int nParam2)

        {

            return nParam1 + nParam2;

        }

    }

}

Listing 6

Now if you launch the GUI test runner again, you can see that the test cases passed (see Figure 9).

Figure 9

Conclusion

In this article, I've illustrated how programmers can use the test-driven development approach to implement and test a Web service. Now you can apply this approach to your own business solutions.

Login to add your contents and source code to this article
share this article :
post comment
 

WCF Services can be easily tested uing WCFStorm, http://www.wcfstorm.com. Plus, you can also do load tests with it and then save all your test cases in a project file.

Posted by namigop Apr 29, 2009

TDD is a great thing to do to ensure product quality and understandability of modules, services are the right abstraction level to perform test on. An even more interesting scenario to work on will be for stateful services (e.g. Workflow services), where you invoke multiple operations to perform a task, and in between there could be significant amount of idle time. Could you please modify your article a little bit to remember to close the connection, that would help promote best practices. If you don't close the connection, the test will eventually hit the service throttle.

Posted by Au Andrew Apr 21, 2009
Become a Sponsor
PREMIUM SPONSORS
  • Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
    ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications. Visit DynamicPDF here
Team Foundation Server Hosting
Become a Sponsor