Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dependency Injection with Unit Test Use Case

0.00/5 (No votes)
26 Dec 2014 1  
Explained the purpose and implementation of Dependency with a simple working example

Introduction

These days, Dependency Injection is a very commonly used term in object oriented programing. DI is a design pattern which is used to implement loosely coupled components. The main purpose is code maintainability and reusability. You may also have heard of the Dependency Injection container like Unity, Ninject or Spring but Dependency Injection is a simple concept which can be used anywhere, without any Dependency Injection container, and is especially useful in unit testing.

Objective

In this article, we will cover:

  • Dependency Injection implementation and advantages
  • How it can ease writing test cases

To explain DI, let us take an example of Plane. Plane can have multiple classes, i.e., Business, Premium or Economy. Now let's say all these classes implement an Interface ItravelClass.

public interface ITravelClass {      
}
public class Business : ITravelClass {
}
public class Economy: ITravelClass {
}
public class Premium : ITravelClass {
}

Now to implement a plane with business class, we can write:

public class Plane {
private Business businessClass;
}

This is a nice plane this plane class is tightly coupled to the Business class. There's nothing wrong with it, the Business plane is fine but what if we decide to allow economy class. Then we have to modify this class and add reference of Economy class, which is obviously not a good approach.

Using Interface

As Business class implement was implementing the ItravelClass interface. Other classes are also implementing the same interface. Let's think about it. When we design our Plane class, we can instantiate object of IteravelClass here. Let’s do that:

public class Plane {
private ITravelClass travelclass ;
}

But this is just an interface not missing a concrete class so we have to instantiate business class object as shown below:

public class Plane {
private ITravelClass travelclass = new Business();
}

Now, here we are using interface but it still has business object still so tightly coupled. Our problem is still unresolved.

Dependency Injection

As the name says, it is all about injecting dependency and making class loosely coupled. That means we have to make Plane class independent of concrete class and let it decide the concrete class implementation at run time.

Constructor Based Injection

One way to inject dependency is to pass the concrete implementation of the depending class to the constructor. Our plane class would become:

public class Plane {

private ITravelClass travelclass;

        public Plane(ITravelClass travelclass){
            this.travelclass = travelclass;
        }  
} 

Now, we can create plane with any class by passing the concrete class from the client. For example:

class Program{

        //constructor based DI client

        static void Main(string[] args){

            //constructor based DI client
            Plane myBusinessPlane = new Plane(new Business());
            myBusinessPlane.setClass(new Business());
            Plane myEconomyPlane = new Plane(new Economy());
             myEconomyPlane.setClass(new Business());
            Console.ReadLine();
        }      
    }

Property Based Injection

We can also inject dependency by using setter in the plane class as shown below:

public class Plane{      

 private ITravelClass travelclass;

      public ITravelClass planeclass { 
        get {return travelclass ;}
        set { travelclass = value;}
      }

}

Implementation of client will change accordingly:

class Program
    {
        //DI using setter

        static void Main(string[] args){
            Plane myBusinessPlane = new Plane();
            myBusinessPlane.planeclass = new Business();
            Console.WriteLine(myBusinessPlane.planeclass.getServices());
            Console.WriteLine("---------------------------------");
            Plane myEconomyPlane = new Plane();
            myEconomyPlane.planeclass = new Economy();
            Console.WriteLine(myEconomyPlane.planeclass.getServices());
            Console.ReadLine();
    }

Unit Test: Use Case for Dependency Injection

Till now, we have seen how to implement dependency injection. Now what are the advantages of doing this. One was we have removed tight coupling from Plane class. Now one of the real time frequently used use case of Dependency injection is in writing unit test cases. In the above example, we have used simple classes with any complex implementation. Let’s change ITravelClass and add two methods SetClass and getServices and implement these in other classes.

void setClass(String classtype, String priceRange);
String getServices();

Suppose in real example these methods could involve some complex DB operations which we don’t want to use in our test case. So we can create a mock class which implements ITravelClass and have our own test data inside methods.

public class MockClass :ITravelClass
    {
        private String classtype = "MockClass";
        private String priceRange = "TEST data";

        public void setClass(String classtype, String priceRange)
        {
            this.classtype = classtype;
            this.priceRange = priceRange;
        }
        public String getServices()
        {
            return classtype;
        }
    }

Implementation of Unit test class is as follows:

[TestClass]

    public class ProgramTest
    {
        [TestMethod]
        public void TestPlane(){
            Plane myMockPlane = new Plane();
             myMockPlane.planeclass  = new MockClass(); 
            Assert.AreEqual("MockClass", myMockPlane.planeclass.getServices());
        }
    }

So now we have implemented a dependency injection and successfully used it in Unit test case. To sum up, some important points we covered are listed below:

  • Use interface rather than concrete class to avoid tight coupling of dependency in the class.
  • Dependency injection can be done in various ways like constructor injection or property setter injection.
  • Dependency injection makes unit testing very flexible.

For complete implementation, download the attached code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here