Click here to Skip to main content
15,884,425 members
Articles / Programming Languages / C#

Dependency Injection with Unit Test Use Case

Rate me:
Please Sign up or sign in to vote.
4.67/5 (5 votes)
26 Dec 2014CPOL3 min read 23.5K   76   8   9
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.

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
public class Plane{      

 private ITravelClass travelclass;

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

}

Implementation of client will change accordingly:

C#
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.

C#
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.

C#
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:

C#
[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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


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

Comments and Discussions

 
GeneralMy vote of 4 Pin
Santhakumar Munuswamy @ Chennai16-May-15 2:00
professionalSanthakumar Munuswamy @ Chennai16-May-15 2:00 
GeneralRe: My vote of 4 Pin
Sudhir Dutt Rawat18-May-15 20:54
Sudhir Dutt Rawat18-May-15 20:54 
QuestionPlease consider Pin
Nelek31-Dec-14 2:25
protectorNelek31-Dec-14 2:25 
QuestionProperty based injection is not explained in right way. Pin
Amit Gupta AG29-Dec-14 9:11
Amit Gupta AG29-Dec-14 9:11 
AnswerRe: Property based injection is not explained in right way. Pin
Sudhir Dutt Rawat30-Dec-14 18:17
Sudhir Dutt Rawat30-Dec-14 18:17 
Right Thanks correction is below

public class Plane
{


private ITravelClass travelclass;

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

}
AnswerRe: Property based injection is not explained in right way. Pin
Sudhir Dutt Rawat30-Dec-14 18:18
Sudhir Dutt Rawat30-Dec-14 18:18 
QuestionThis is not Dependency Injection Pin
SledgeHammer0126-Dec-14 11:02
SledgeHammer0126-Dec-14 11:02 
AnswerRe: This is not Dependency Injection Pin
pt140126-Dec-14 21:43
pt140126-Dec-14 21:43 
QuestionThis was a tip... Pin
OriginalGriff26-Dec-14 5:50
mveOriginalGriff26-Dec-14 5:50 

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.