Click here to Skip to main content
15,867,835 members
Articles / DevOps / Testing

MOQ and C# (inc. Synchronized and Asynchronized WCF Service Calls)

Rate me:
Please Sign up or sign in to vote.
4.88/5 (7 votes)
4 Apr 2011CPOL7 min read 45.1K   798   28   5
Mocking your .NET services (inc. asynchronous calls) or class libraries with MOQ

Introduction

When it comes to 'Unit Testing' your code - you will want to test a small code base at a time (i.e. each method within your respective classes). This will lead to greater stability within your overall project, if you know that each method does what it is expected. When testing the working of a method, you will want to exclude external calls to databases, third party DLLs or your own services, so that you can better 'Black Box Test' your application. To exclude these external resources from your code and be able to replace these method call returns with your own method call returns - you will need to mock your tests. There are a number of very well written mocks available - but MOQ is one that is easy to get up and running quickly - which is a huge bonus when a developer has to unit test their code.

Background

What is a Mock

Mock objects are instantiated objects that mimic the behavior of real objects in a controlled environment – thus supplying an informed (expected) result.

Why Mock

It is best to design libraries to have a minimal set of dependencies, but sometimes this is not practical, especially when the library has not been designed with testability in mind. When unit testing libraries with a complex set of dependencies, these dependencies may require difficult or time-consuming setup procedures which are detrimental to the test itself. It will be very common that the code that you are unit testing will depend on a dependency that hasn't been fully tested yet or eventfully designed. But that shouldn't stop a developer from being able to test their new procedural code – thus you will mock up the return from this (not yet tested) dependency and test that your code behaves as expected. Mocking also gives you a better code coverage - using tools like Ncover can greatly increase your teams productivity, in that you can see what code paths have been tested and which paths still need more testing – thus mocks can greatly enhance your code coverage by letting you implement paths that would normally of needed more setup (calling services or populating a database table with certain data) to perform your test.

Mocks become (necessary) advantageous when an method/object being unit tested has the following characteristics:

  • Has states that are difficult to create or reproduce (e.g. a network error, database server down)
  • Is slow (e.g. Make multiple calls to multiple services, which would have to be initialized before the test)
  • Does not yet exist or may change behavior
  • Would have to include information and methods exclusively for testing purposes (and not for its actual task)

Difference Between A Mock Test and an Integration Test

Basically, with an integration test, you are performing an end-to-end test of your system to see that it functions as a whole system as expected. But with mocking, you are looking to see if your smaller snippet of code (function) works as expected. So, in saying that, an integration test is made up of many smaller units of code (which you will have already mocked individually).

Using the Code

Visual Studio Project Structure

In Fig 1, you can see the structure I have created for the solution. I have a class definition, a couple of class libraries (the MainApp will be equivalent to MainContext class in your application). A group of tests projects and finally a WCF service.

MoqAndDotNet/ProjectStructure.png

Fig. 1

Fig 2 shows an expanded solution. The idea is that the 'MoqDllTests' project will mock the calls to the DLLs (DatabaseLib and FileLib) methods that are used in the 'MainApp' project. The second test project, 'MoqServiceTests', will mock calls to the WCF service 'MoqService', from calls within the class 'ViewModel', inside this test project (this class 'ViewModel' would be like a Context class).

MoqAndDotNet/ProjectExpanded.png

Fig. 2

Pet Class

The Pet class below - is just a 'plain old class object' (POCO), with some private properties, constructors, enumerations and setters & getter. This class is used for passing information back from the (external) services or class libraries - thus their contents will be mocked in certain circumstances.

C#
[Serializable]
  public class Pet
  {
      /// <summary>
      /// Initializes a new instance of the <see cref="Pets"/> class.
      /// </summary>
      public Pet(string name, int age, AnimalType typeOfAnimal, List<Food> canEat)
      {
          this.Age = age;
          this.CanEat = canEat;
          this.TypeOfAnimal = typeOfAnimal;
          this.Name = name;
      }

      /// <summary>
      /// Initializes a new instance of the <see cref="Pet"/> class.
      /// </summary>
      public Pet() { }

      // setters & Getters
      public string Name { set; get; }
      public int Age { set; get; }
      public AnimalType TypeOfAnimal { set; get; }
      public List<Food> CanEat { set; get; }

      [Serializable]
      public enum Food
      {
          Hay,
          Chum,
          Milk
      }

      [Serializable]
      public enum AnimalType
      {
          Dog,
          Cat,
          Horse,
          Rabbit
      }
  }

Main Class

Below is the code for the main application - maybe in your case, the start page, for example. I basically want to test these methods below function properly - but I do not want to test the methods that they call, if they are outside the scope of this test (i.e., making a call to a database or the DLLs - which they all do in some form or another.)

C#
public class Context
    {
        #region Class Variables
        
        public IFileController MyFile { get; set; } // File IO layer
        public IDatabaseController MyDatabase { get; set; } // Database layer
        public IPetsController MyPetService { get; set; } // Wcf service

        #endregion

        #region Constructors
        
        /// <summary>
        /// Initializes a new instance of the <see cref="Context"/> class.
        /// </summary>
        /// <param name="fileService">The file service.</param>
        /// <param name="databaseService">The database service.</param>
        /// <param name="petService">The pet service.</param>
        public Context(IFileController fileService, IDatabaseController databaseService, 
            IPetsController petService)
        {
            this.MyFile = fileService;
            this.MyDatabase = databaseService;
            this.MyPetService = petService;            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Context"/> class.
        /// </summary>
        public Context()
        {
            this.MyFile = new FileController();
            this.MyDatabase = new DatabaseController();
            this.MyPetService = new PetsService.PetsControllerClient();
        }

        #endregion

        #region Class Methods

        /// <summary>
        /// Database layer call
        /// </summary>
        /// <returns></returns>
        public int DoubleNumberOfKennelsInDatabase()
        {            
            return this.MyDatabase.NumberOfKennelsInDatabase() * 2;             
        }

        /// <summary>
        /// File IO layer call
        /// </summary>
        /// <returns></returns>
        public int TrebleNumberOfKennelsOnFile()
        {
            return this.MyFile.NumberOfKennelsOnFile() * 3; 
        }

        /// <summary>
        /// Wcf Service call
        /// </summary>
        /// <returns></returns>
        public int QuadrupalNumberOfKennelsOnWcfService()
        {
            return this.MyPetService.NumberOfDogs() * 4;
        }

        #endregion
       
    }

Below is the declaration for Interface of the database access layer and the implementation of the database layer itself. I have only two simple methods that I use, which are used by the (Context) class above. Notice that I overload the constructor to be a normal empty parameter and to also take references to external DLLs or references, this constructor is the main reason why I am able to mock the methods inside this class - meaning that I am able to inject mock references into the database layer class, but will not interfere with the workings of the methods in the layer itself.

C#
 namespace DatabaseLib
{
    public interface IDatabaseController
    {
        int NumberOfKennelsInDatabase();
        DateTime ClosingTimeKennels();
    }
}
C#
 namespace DatabaseLib
{
    public class DatabaseController : IDatabaseController
    {
         public IPetsController MyPetService { get; set; } // Wcf service

        public DatabaseController() { }
        public DatabaseController(IPetsController petService) { 
            this.MyPetService = petService; }

        public int NumberOfKennelsInDatabase()
        {
            // makes connection to database...etc
            return 10;
        }

        /// <summary>
        /// Current time plus two hour will be returned from the service .
        /// </summary>
        /// <returns></returns>
        public DateTime ClosingTimeKennels()
        {            
            return MyPetService.GetCurrentDateTime().AddHours(1);
        }
    }
}

Unit Tests And Setting Up Mocking Object

The code snippet below shows how I am setting up the mock instances within my test class. I plan to mock the IDatabase, IFile and the MoqService objects. So that when certain (mocked) methods are called, they will not go to the database, file system or web service but just return what I have instructed them to return.

Notice that inside the Init() method, I create some dummy data (Pet class) that will account for the expected data when returned by the mocked methods. This is 'Black Box Testing', comparing what was returned to what was expected.

C#
#region Class Variables
        
        Mock<IDatabaseController> moqDB;
        Mock<IFileController> moqFile;
        Mock<ProjectCode.PetsService.IPetsController> petService;
        Context context;        
        List<Pets.Pet> lstPets;

        #endregion

        #region Constructor
        
        public ContextTests(){}

        #endregion

        #region Setup

        [TestFixtureSetUp]
        public void Init()
        {
            moqDB = new Mock<IDatabaseController>();
            moqFile = new Mock<IFileController>();
            petService = new Mock<ProjectCode.PetsService.IPetsController>();            
            context = new Context(moqFile.Object, moqDB.Object, petService.Object);

            lstPets = new List<Pets.Pet>();
            var pet = new Mock<Pets.Pet>(MockBehavior.Strict).SetupAllProperties();
            var petStub = pet.Object;

            petStub.Age = 20;
            petStub.CanEat = new List<Pets.Pet.Food>();
            petStub.CanEat.Add(Pets.Pet.Food.Milk);
            petStub.Name = "TopCat";
            petStub.TypeOfAnimal = Pets.Pet.AnimalType.Cat;
            lstPets.Add(petStub);

            petStub.Age = 10;
            petStub.CanEat.Clear();
            petStub.CanEat.Add(Pets.Pet.Food.Chum);
            petStub.CanEat.Add(Pets.Pet.Food.Milk);
            petStub.Name = "TopDog";
            petStub.TypeOfAnimal = Pets.Pet.AnimalType.Dog;
            lstPets.Add(petStub);
        }

#endregion

A Mocked Call To A Class Library

I want to make sure the database class method 'NumberOfKennelsInDatabase()' will return a certain number when it is executed by the method 'DoubleNumberOfKennels()' in the 'MainContext' class. In the example code, I am telling the method 'NumberOfKennelsInDatabase()' to return 25 whenever it is called. All the 'DoubleNumberOfKennels()' does is double the returned value, thus I know what to Assert against the value coming back from 'DoubleNumberOfKennels()'.

Remember, we are testing the code in the 'Context' class, thus we are mocking the code in the database class (one layer extracted from it).

C#
/// <summary>
/// A mocking of a database call within the database dll         
/// </summary>
[Test(Description = "Mocking a Context class method that makes a db call operation.")]
public void TestMockDBCall()
{
    moqDB.Setup(db => db.NumberOfKennelsInDatabase()).Returns(25);            

    int retValue = context.DoubleNumberOfKennelsInDatabase();
    Assert.IsTrue(retValue == 50.0);
}

Mocking An Expected Exception

A developer will need to mock certain known exceptions and test how their code handles such exceptions. Thus, you are able to throw a mocked exception back to your calling class and thus test how your code handles the result from the mock.

C#
[Test(Description = "Test for an expected thrown exception")]
[ExpectedException(typeof(ArgumentException))]
public void TestThrownExceptionNumberOfDogs()
{
    // exception message
    const string exceptionMessage = "Non-Initialised Object On Server.";
 
    Mock<IPetsController> petServiceTests = new Mock<IPetsController>();
  
    // setup (mock) the test
    petServiceTests.Setup<int>(method => method.NumberOfDogs()).Throws(
                new ArgumentException(exceptionMessage)); 
    IPetsController value = petServiceTests.Object; // pass mock instance to interface
 
    int returns = value.NumberOfDogs(); // call mock (no int value returned)
 
    #region Alternative code
    //try
    //{
    //    int returns = value.NumberOfDogs(); // call mock
    //}
    //catch (Exception ex)
    //{
    //    // test exception is as expected
    //    Assert.IsTrue(ex.Message.Equals(exceptionMessage)); 
    //}                     
    #endregion
}

Mocking Synchronized Calls (MoqServiceTests project)

In the second test project, I perform the synchronized and asynchronized tests, in the code below, there is an asynchronized method and its corresponding completed method. I want to test that I can call each individually, and then that I can call the 'Begin' method and test what was returned in the 'End' method.

To so this, I have a class create a new Context class called 'ViewModel'. This class will be my main class that calls the service methods below. So, I want to test these calling methods in 'ViewModel' and mock the service calls.

C#
private IDatabaseController iDatabaseController;
public PetsController() { iDatabaseController = new DatabaseController(); }
public PetsController(IDatabaseController databaseService) {
            iDatabaseController = databaseService; }

#region Async. Method
        
/// <summary>
/// Begins the get all names by age.
/// </summary>
/// <param name="age">The age.</param>
/// <param name="callback">The callback.</param>
/// <param name="asyncState">State of the async.</param>
/// <returns></returns>
public IAsyncResult BeginGetAllPetsByAge(int age, AsyncCallback callback,
            object asyncState)
{      
    Pet pet = new Pet();
    List<Pets.Pet> listPets = new List<Pets.Pet>();

    // PERFORM THE WORKING OUT HERE            
    pet.Age = 10;
    pet.CanEat.Add(Pet.Food.Hay);
    pet.Name = "Jumper";
    pet.TypeOfAnimal = Pet.AnimalType.Horse;
    listPets.Add(pet);

    return new CompletedAsyncResult<List<Pets.Pet>>(listPets);
}

/// <summary>
/// This method is called by the BEGIN method, it does not need to 
/// be called by the client.
/// </summary>
/// <param name="r">Result of processing</param>
/// <returns></returns>
public List<Pets.Pet> EndGetAllPetsByAge(IAsyncResult r)
{
    CompletedAsyncResult<List<Pets.Pet>> result = 
                r as CompletedAsyncResult<List<Pets.Pet>>;
    return result.Data;
}

/// <summary>
/// Tests the begin async.
/// </summary>
[Test]
public void TestBeginAsync()
{
    AsyncCallback callback = new AsyncCallback(CompletePets);
    Mock<IAsyncResult> mockAsyncResult = new Mock<IAsyncResult>();
    IAsyncResult expectedAasyncResult;
    Mock<IPetsController> petServiceTests = new Mock<IPetsController>();
            
    petServiceTests.Setup(async => async.BeginGetAllPetsByAge(It.IsAny<int>(), 
                It.IsAny<AsyncCallback>(),
                It.IsAny<object>())).Returns(mockAsyncResult.Object);
    IPetsController value = petServiceTests.Object; 	// pass mock instance 
							// to interface
    expectedAasyncResult = value.BeginGetAllPetsByAge(10, callback, new object());    

    // using the callback to test that a method was indeed called.
    Assert.IsTrue(expectedAasyncResult == mockAsyncResult.Object); 
}

/// <summary>
/// Tests the end async.
/// </summary>
[Test]
public void TestEndAsync()
{
    List<Pets.Pet> expectedResult = new List<Pets.Pet>();

    AsyncCallback callback = new AsyncCallback(CompletePets);
    Mock<IAsyncResult> mockAsyncResult = new Mock<IAsyncResult>();            
    Mock<IPetsController> petServiceTests = new Mock<IPetsController>();

    petServiceTests.Setup(async => async.EndGetAllPetsByAge(
                It.IsAny<IAsyncResult>())).Returns(this.lstPets);
    IPetsController value = petServiceTests.Object; 	// pass mock instance 
							// to interface
    expectedResult = value.EndGetAllPetsByAge(mockAsyncResult.Object);

    // using the callback to test that a method was indeed called.
    Assert.IsTrue(this.lstPets == expectedResult); 
}

Mocking Asynchronized Calls

Below, I am performing an asynchronized test, in that I am mocking the 'Begin' and the 'End' method calls in the WCF Service. I am calling the method 'ProcessAsync(int)' in the 'ViewModel' class that performs the initial call 'Begin' to the service. Then, I am asserting that the value I expect the completed event to pass back was actually passed back.

C#
/// <summary>
/// Tests the async completed.
/// </summary>
[Test]
public void TestAsyncCompleted()
{
    AsyncCallback callback = null;
    IAsyncResult ar = new Mock<IAsyncResult>().Object;
    var wcfService = new Mock<IPetsController>();

    // mock Begin
    wcfService.Setup(async => async.BeginGetAllPetsByAge(It.IsAny<int>(),
                It.IsAny<AsyncCallback>(),null))
                .Callback((int age, AsyncCallback cb, object state) => callback = cb)
                .Returns(ar);

    // mock End
    wcfService.Setup(async => async.EndGetAllPetsByAge(It.IsAny<IAsyncResult>()))   
                .Returns(this.lstPets);

    var sut = new ViewModel(wcfService.Object);
    sut.ProcessAsync(10);
    callback(ar);

    Assert.AreEqual(this.lstPets, sut.ListOfPets);          
}

Mocking Database Call in Asynchronized Calls

Below, I inject a mocked database layer object into the service constructor, mocking a particular database call method 'NumberOfKennelsInDatabase()' that is used by the service method 'BeginServiceCallsDB'. The asynchronized call below is a little different to the one used above in that I am testing the IAsyncResult that comes back from the asynchronized call.

C#
/// <summary>
       /// Tests the async method and mock DB call in service.
       /// </summary>
       [Test]
       public void TestAsyncMethodAndMockDBCallInService()
       {
           // mock the database call that will be performed inside the service method
           Mock<DatabaseLib.IDatabaseController> MockDB =
               new Mock<DatabaseLib.IDatabaseController>();
           MockDB.Setup(meth => meth.NumberOfKennelsInDatabase()).Returns(2);

           AsyncCallback callback = new AsyncCallback(CompletePets);
           IAsyncResult expectedAasyncResult;
           IPetsController petServiceTests = new PetsController(MockDB.Object);
           expectedAasyncResult = petServiceTests.BeginServiceCallsDB(callback,
               new object());

           Assert.IsTrue(((Pets.CompletedAsyncResult<int>)
           (expectedAasyncResult)).Data == 4);

       }

Useful Links

References Used Within the Project

MoqAndDotNet/TestsReferences.png

NUnit Results

MoqAndDotNet/NunitResults.png

License

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


Written By
Architect
Ireland Ireland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionDefault constructor Pin
Himanshu Thawait13-Oct-14 9:27
Himanshu Thawait13-Oct-14 9:27 
SuggestionAsynchronized Calls setup MOQ 4.2+ Pin
Himanshu Thawait13-Oct-14 8:55
Himanshu Thawait13-Oct-14 8:55 
GeneralRe: Asynchronized Calls setup MOQ 4.2+ Pin
Bert O Neill11-Nov-14 3:26
Bert O Neill11-Nov-14 3:26 
GeneralMy vote of 5 Pin
Kanasz Robert28-Sep-12 5:52
professionalKanasz Robert28-Sep-12 5:52 
Excellent article
QuestionI Vote 5 Pin
Member 70171542-Aug-12 2:43
Member 70171542-Aug-12 2:43 

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

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