Click here to Skip to main content
Click here to Skip to main content

How to Mock a WCF Service

, 27 Jan 2012
Rate this:
Please Sign up or sign in to vote.
How to Mock a WCF Service while writing a unit test

Introduction

Unit tests have become integral part of any build now days. Unit tests should be written normally for smallest units of code i.e. methods doing some specific and independent work. But, what if your method is calling different layers (like Method => BusinessLogicLayer =>DataLayer) to get its work done and you want to write unit tests for that? If your unit test also calls all these layers in actual it doesn’t go with the actual purpose of unit tests. Unit test should definitely not call other layers for sure. Situation becomes a bit tricky and difficult when you want to write a unit test for a method which calls a WCF service internally.

To overcome from this problem we use Mock Frameworks. There are many Mock frameworks available in the market but I will be discussing mocking using MOQ here. Let us take wcf scenario and try to mock a wcf method using MOQ mock framework while writing a unit test for wcf client method (which calls wcf service).

I will highlight some other features also later in this article.

Using the Code

My wcf service WCFService is derived from an interface IWCFService and has a method GetData(int value)

namespace WCFService
{

    public class WCFService : IWCFService

    {
        public string GetData(int value)

        {
            return string.Format("You entered: {0}", value);

        }

    }
}

A wcf client WCFClient consumes WCFService using a service agent WCFServiceAgent. Service agent implements a method HitWCFService() which calls service method GetData()

namespace WCFClient
{
    public class WCFServiceAgent

    {
        IWCFService wcfService;

        public WCFServiceAgent()
        {

            this.wcfService = new WCFServiceClient();
        }

        // constructor for unit test
        public WCFServiceAgent(bool isUnitTest)

        {
            this.wcfService = UnityHelper.IoC.Resolve<IWCFService>();

        }

        public string HitWCFService()

        {
            int val = 1; string retVal = string.Empty;

            // call wcf service
            retVal = this.wcfService.GetData(val);

            return retVal;
        }

    }
}

Now, we want to write a unit test for HitWCFService(). To avoide actual service call we need to mock wcfService.GetData(val) method.

namespace WCFClientTest
{
    [TestClass]

    public class WCFClientUnitTest
    {

        [TestMethod]
        public void MockWCFService()

        {
            string val = "MockedValue";string actualRetVal;

            // mock wcf interface
            Mock<IWCFService>wcfMock = new Mock<IWCFService>();

            // setup for wcf service GetData method
            wcfMock.Setup<string>(s=> s.GetData(It.IsAny<int>())).Returns(val);

            // create object to register with IoC
            IWCFService wcfMockObject = wcfMock.Object;

            // register instance
            UnityHelper.IoC = new UnityContainer();
            UnityHelper.IoC.RegisterInstance<IWCFService>(wcfMockObject);


            // create ServiceAgent object using parameterized constructor (for unit test)

            WCFServiceAgent serviceAgent = new WCFServiceAgent(true);

            // method call to be tested

            actualRetVal = serviceAgent.HitWCFService();

            // verify if the expected method called during test or not
            wcfMock.Verify(s => s.GetData(It.IsAny<int>()), Times.Exactly(1));

            Assert.AreEqual("MockedValue", actualRetVal, "Not same.");
        }

    }
}

In above written example, we first create a mock object of IWCFService interface. Mock<IWCFService> wcfMock = new Mock<IWCFService>();

Just to remember, mock object cannot be created for a concrete class i.e. it is not possible to write something like

Mock<WCFService> wcfMock = new Mock<WCFService>().wcfMock.Setup<string>(s => s.GetData(It.IsAny<int>())).Returns(val);

using above specified line of code we tell mock framework that we wish to mock GetData method and the return value will be val. In other words, when GetData() is invoked imitate that this method is called and returned val.

Now, we register the instance of wcfMockObject with IoC which bounds IoC to return the same object when statement IoC.Resolve() is encountered.

// register instance
UnityHelper.IoC = new UnityContainer();
UnityHelper.IoC.RegisterInstance<IWCFService>(wcfMockObject);
I handled the situation with a small trick further. I used parameterized constructor to create the service client object in service agent. If you see the code, the simple constructor is used to create the ServiceAgent object (when actual application creates the object) but for unit test I used the parameterized constructor where IoC.Resolve gives me the registered mock object.
// constructor for unit test

public WCFServiceAgent(bool isUnitTest)
{

    this.wcfService = UnityHelper.IoC.Resolve<IWCFService>();
}
For your reference UnityHelper is nothing but as follows:
namespace WCFClient
{

    public static class UnityHelper
    {

        public static UnityContainer IoC; 
    }
}
Now, second last line of my unit test method verifies if the expected method call happened or not.
// verify if the expected method called during test or not

wcfMock.Verify(s => s.GetData(It.IsAny<int>()),Times.Exactly(1));
This line can be written as
wcfMock.Verify(s => s.GetData(4), Times.Exactly(1));

but then your setup method should also be

wcfMock.Setup<string>(s => s.GetData(4)).Returns(val);

However, this will create problem if the parameter being passed to the mocked method is created or initialized inside the method we are writing the unit test for. I deliberately created the parameter val (val = 1) inside HitWCFService. The mock framework considers both the methods different (GetData(4) and GetData(1) are not same) and when you verify it, it throws an error saying something like; “expected once but never called”.

If you don’t want MOQ to compare parameters use It.IsAny<int>(). This causes MOQ to ignore parameters while expecting mocked method.

For more, please see demo application.

- Amit Shrivastava, System Analyst, Avanade/Accenture (Gurgaon, India)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Amit Shrivastava Gurgaon
Program Manager
India India
No Biography provided

Comments and Discussions

 
QuestionIoC containers are not a crutch Pinmemberdarthg8r25-Apr-13 3:12 
Generaltesting WCF service with MEF and Moq Pinmemberyoavniran28-Oct-12 6:45 
SuggestionDon't change your code for unit testing, just unit test it PinmemberStephen Inglish28-Jan-12 1:12 
SuggestionMy vote of 3 Pinmemberi.j.russell24-Jan-12 0:37 
GeneralRe: My vote of 3 PinmemberMember 290234324-Jan-12 1:50 
GeneralRe: My vote of 3 PinmemberMember 290234324-Jan-12 1:51 
but anyways ... thanks for your comments by heart .. Smile | :)
GeneralMy vote of 3 PinmemberNewSilence23-Jan-12 14:40 
QuestionRe: My vote of 3 Pinmemberi.j.russell24-Jan-12 0:30 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 28 Jan 2012
Article Copyright 2012 by Amit Shrivastava Gurgaon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid