Using TypeMock.NET to mock an external dependency
Posted by Marcus Wyatt on 15 January 2006
In the scenario where your class consumes an external Web Service, testing your class is hard and difficult due to this external dependency on the Web Service. You could use a Service Stub, where you separate the dependency using an interface, but this forces you to create more code due to creating an interface and the service stub implementation. So I thought there must be a better, easier, less work way to mock this external dependency and here TypeMock.NET comes to the rescue. Well, let’s see some code:
I’ve created the following web service as an external dependency to consume in my class:
namespace DataLogic
{
/// <summary>
/// Simple WS to return a customer object to test
/// how we will replace this external dependency
/// </summary>
public class DataService : WebService
{
[ WebMethod ]
public DataResponse GetCustomer( DataRequest request )
{
DataResponse response = new DataResponse();
response.Customer = new Customer();
response.Customer.CustomerNumber = request.CustomerNumber;
response.Customer.Firstname = "Maruis";
response.Customer.Surname = "Marais";
response.Customer.Title = "Mr.";
return response;
}
}
}
I’ve created the following web service as an external dependency to consume in my class:
using System;
using System.Net;
using DataService;
namespace BusinessProcess
{
public class Inquiry
{
// should be read from the config file of something
private string url = @"http://localhost/DataService.asmx";
public Customer GetCustomerDetailsDataInquiry( string customerNumber )
{
DataServiceRequest request = null;
DataServiceResponse response = null;
Customer customer = null;
// Create the Request
request = CreateDataInquiryRequest( customerNumber );
// Call the Data Web Service
response = GetCustomerInquiryDataResponse( request );
// Validate the response returned
// is the correct customer that is requested
ValidateDataResponse( request, response );
// Convert the data response to a
// customer to return
customer = FormatDataResponse( response );
// Return the customer object
return customer;
}
protected DataServiceResponse GetCustomerInquiryDataResponse( DataServiceRequest request )
{
// this is the dependency we want to replace
DataService service = new DataService();
service.Credentials = CredentialCache.DefaultCredentials;
service.Url = url;
// this is the specific call we want to replace
DataServiceResponse response = service.GetCustomer( request );
return response;
}
protected void ValidateDataResponse( DataServiceRequest request, DataServiceResponse response )
{
// here we want to confirm the requested customer is the correct
// customer returned by the data web service, if it fails we want
// to throw an exception
if( request.CustomerNumber != response.Customer.CustomerNumber )
{
throw new Exception( "Incorrect customer returned" );
}
}
// some more methods and code
}
}
Note: The GetCustomerInquiryDataResponse method is declared as protected, without a virtual modifier. Most of the other Mocking frameworks would require you to modify the method to be public and virtual or you would need to extract an interface for the Inquiry class to be able to mock this method. TypeMock doesn’t need this to be able to mock the dependency; in actual fact TypeMock doesn’t mock the method. It actually mocks the DataService.
Here is the unit testing code where we used TypeMock.NET to replace the dependency on the Data Web Service. TypeMock ‘intercept’ the calls to Dataservice and mock these up:
using System;
using TypeMock;
using NUnit.Framework;
using BusinessProcess.ClassLib;
namespace BusinessProcess.Test
{
[ TestFixture ]
public class TestCustomerInquiry
{
// should be read from the config file of something
private string url = @"http://localhost/DataService.asmx";
[ Test ]
public void GetCustomer_When_ValidCustomerNumberSupplied()
{
// 1. Initialize Type Mocks
MockManager.Init();
// Setup the Customer Details Inquiry class to test
Inquiry inquiry = new Inquiry();
// setup the expected object
Customer expected = new Customer( "1234", "Grant", "Archibold", "Mr." );
// 2. the DataService webservice is now being mocked
Mock dataServiceMock = MockManager.Mock( typeof( DataService ) );
// 3. setup our expectations
dataServiceMock.ExpectSet( "Url" ).Args( url );
dataServiceMock.ExpectAndReturn( "GetCustomer", GetResponse() );
// GetCustomerDetailsDataInquiry should return a customer object we expect
Customer actual = inquiry.GetCustomerDetailsDataInquiry( "1234" );
// verify the objects are the same
Assert.AreEqual( expected.CustomerNumber, actual.CustomerNumber, "Customer Numbers differ" );
Assert.AreEqual( expected.FirstName, actual.FirstName, "FirstName differ" );
Assert.AreEqual( expected.Surname, actual.Surname, "Surname differ" );
Assert.AreEqual( expected.Title, actual.Title, "Title differ" );
// 4. Verify that all calls were made
MockManager.Verify();
}
#region Helper Methods
private static DataServiceResponse GetResponse()
{
// Business Logic Response
DataServiceResponse mockResponse = new DataServiceResponse();
mockResponse.Customer = new DataService.Customer();
mockResponse.Customer.CustomerNumber = "1234";
mockResponse.Customer.Firstname = "Grant";
mockResponse.Customer.Surname = "Archibold";
mockResponse.Customer.Title = "Mr.";
return mockResponse;
}
#endregion
}
}
Let’s see what we did here:
- We initialize the TypeMock framework.
- Setup mocking of the DataService – all calls to data service will be intercepted.
- Here we tell TypeMock.NET what calls to expect, what parameters to validate and what results to return.
- Finally we would verify that all the expectations where fulfilled.
You might have noticed that I don’t pass any mocked object to the code that we are testing. This code is elegant and we are able to keep to the guidelines of writing good tests:
- Test isolated code – Here we isolate our code completely by returning mocked values and by checking the ‘messages’ between the objects.
- Tests should be fast – We don’t need to setup coupled code and this makes our test fast.
- Tests have to be self contained – The entire scenario is contained in the test. (No need to connect to a corrupt database)
- Tests have to be run by multiple users – As there are no shared resources this issue is fine.
- Tests should be independent – This test can run alone.
- Maintainable – As the test is simple, it is easier to maintain. Even if the data service changes its internal configuration this won’t effect the test
How does TypeMock.NET work?
TypeMock.NET uses an Aspect Oriented Programming Design, by creating a Mock aspect. Internally it uses the .NET Framework profiler API to monitor an application’s execution. When a method is loaded by the CLR, TypeMock.NET retrieves the IL and replaces it with instrumented IL code. TypeMock.NET does not change your original IL code, it simply inserts new code that calls the TypeMock.NET framework and returns mocked values
In the following test we test the ValidateDataResponse method throws the correct exception when we force an incorrect Customer to be returned (The mock returns a customer with customer number “1234” when the customer number we requested was “4567”):
[ Test ]
[ ExpectedException( typeof( Exception ), "Incorrect customer returned" ) ]
public void ThrowException_When_CustomerNumberDifferFromRequestNumber()
{
// Data Logic Response
DataServiceResponse mockResponse = new DataServiceResponse();
mockResponse.Customer = new ClassLib.DataService.Customer();
mockResponse.Customer.CustomerNumber = "1234";
mockResponse.Customer.Firstname = "Grant";
mockResponse.Customer.Surname = "Archibold";
mockResponse.Customer.Title = "Mr.";
// Setup the Object to test
inquiry = new Inquiry();
// the DataService webservice is now being mocked
Mock dataServiceMock = MockManager.Mock( typeof( DataService ) );
// set up our expectations
dataServiceMock.ExpectSet( "Url" ).Args( url );
dataServiceMock.ExpectAndReturn( "GetCustomer", mockResponse );
// GetCustomerDetailsDataInquiry should return a customer object we expect
Customer actual = inquiry.GetCustomerDetailsDataInquiry( "4567" );
// if this line is reached, the exception is
// not thrown, thus test fail
Assert.Fail( "An exception should have occurred." );
}
This type of testing would be impossible when doing integration or acceptance testing, thus you wouldn’t be able to test this exception behavior.
With TypeMock’s virtual mock ability it is now easy to mock any external dependency and test code in isolation without having to create stubs, interfaces or any other test friendly designs. Will this ability to easily mock these dependencies now cause us to write code that is more coupled due to the fact that we don’t have to think so much about designing our code with testing in mind? Maybe, it will. But I think that the ability that TypeMock.NET gives us, will help us to write better tests giving us better code coverage and the ability to produce well tested code faster. The only problem is that TypeMock.NET is a commercial product, which will hamper the adoption of the framework.
tags: coding-practices, development, framework, oop, tdd, testing, xp
Currently listening to: hiller-Ruhe – Winamp *** 48. DANNY TENAGLIA – 21 Schiller-Ruhe






Scott Hanselman's Computer Zen - Hanselminutes Podcast 32 - Mock Objects said
[...] Example of using TypeMock (i5c) [...]
Anjan Saha said
A very good article indeed..
Ivo said
Hi, interesting article. I have a question: should the external classes be MarshalByRef in order to let TypeMock intercept the calls?
Thanks!
Maruis Marais said
It’s such a long time since I’ve written this article and I have moved on to work in Ruby. But as far as I can remember the external classes don’t need any special Marshaling.
Recursos Mock .NET « Experiencias en Punto Net said
[...] Using TypeMock.NET to mock an external dependency [...]