March 3, 2021
Hot Topics:

Unit Testing with Service Stubs or Mock Types

  • By Paul Kimmel
  • Send Email »
  • More Articles »

Suppose your project also is using a distributed development model and the developers are learning LINQ and WCF, so the service is not ready even though you are ready to implement the service consumer. In this scenario, all you would need is an agreement on the definition of Customer and the service to be provided; that is, request a customer by ID and the service returns the right customer.

To insulate you from dependence on the service provider, you will need to implement a factory, an interface that describes the service's interface, a concrete type, and a mock type. Both the concrete and mock types have to realize—inherit from—the interface. The CustomerServicesFactory simply tries to return an instance of the concrete type, and if an exception occurs, it returns the mock type.

Listing 3 contains a console application that represents the client. I was bored, so the code actually uses a generic delegate to format the Customer—I was showboating a tad. All the code really does is request a Customer and send the customer state to the console.

Listing 3: A console application that sends the Customer state to the console—a little overkill using a generic delegate, but it was fun.

Imports UnitTestingWithMockTypes.ServiceReference1
Imports System.Runtime.CompilerServices
Imports System.Reflection
Imports System.Text

Module Module1

   Sub Main()

   Dim Format As Func(Of Customer, String) = _
      Function(cust) (From prop In cust.GetType(). _
      GetProperties()).Aggregate( _
   New StringBuilder(), Function(builder, p) _
      builder.AppendFormat("{0, -20}: {1}{2}", p.Name, _
      p.GetValue(cust, Nothing), Environment.NewLine), _
      Function(builder) builder.ToString())

   Dim factory As ICustomerServices = _


   End Sub

   <Extension()> _
   Function ToFormattedString(ByVal cust As Customer)

      Return (From prop _
         In cust.GetType().GetProperties()).Aggregate( _
         New StringBuilder(), Function(builder, p) _
            builder.AppendFormat("{0}: {1}{2}", p.Name, _
            p.GetValue(cust, Nothing), Environment.NewLine), _
            Function (builder) builder.ToString())

   End Function
End Module

Listing 4 contains an implementation of the Factory pattern. Factory patterns exist to instantiate objects based on rules. In the example, the Factory defaults to the mock service object in the event of an exception. Listing 5 defines the interface that is part of mock typing (or the service stub enterprise pattern). Notice that the interface mirrors the WCF service.

Listing 4: Using an implementation of the Factory pattern to instantiate an instance of the concrete (or mock, as hardcoded to demonstrate) object as needed.

Public Class CustomerServicesFactory

   Public Shared Function Create() As ICustomerServices
         Throw New Exception
         Return New CustomerServices
      Catch ex As Exception
         Return New MockCustomerServices
      End Try
   End Function

End Class

Listing 5: This interface is part of using mock types; declare the interface to instantiate a class that inherits from it.

Public Interface ICustomerServices

   Function GetCustomer(ByVal customerID As String) As Customer
End Interface

Listing 6 implements the mock service with hard-coded Customer data, and Listing 7 actually consumes the service.

Listing 6: The mock class implements the interface but returns what is essentially test data.

Public Class MockCustomerServices
   Implements ICustomerServices

   Public Function GetCustomer(ByVal customerID As String) _
      As Customer _
      Implements ICustomerServices.GetCustomer

      Dim cust As Customer = New Customer
      cust.CustomerID   = "ALFKI"
      cust.CompanyName  = "Alfreds Futterkiste"
      cust.ContactName  = "Paul Kimmel"
      cust.ContactTitle = "Sales Representative"
      cust.Address      = "Obere Str. 57"
      cust.City         = "Berlin"
      cust.Region       = ""
      cust.PostalCode   = "12209"
      cust.Country      = "Germany"
      cust.Phone        = "030-0074321"
      cust.Fax          = "030-0076541"
      Return cust

   End Function
End Class

Listing 7: Represents the concrete service wrapper, which actually interacts with the service.

Public Class CustomerServices
   Implements ICustomerServices

   Public Function GetCustomer(ByVal customerID As String) _
      As Customer _
      Implements ICustomerServices.GetCustomer

      Dim client As Service1Client = New Service1Client
      Return client.GetCustomer(customerID)

   End Function

End Class

Page 3 of 4

This article was originally published on May 19, 2008

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date