Unit Testing the Dependency Injection in C#

What is Dependency Injection?

Dependency injection is a design pattern that promotes loose coupling between classes by allowing dependencies to be provided from external sources. Instead of a class creating its own dependencies, those dependencies are passed to the class through its constructor, properties, or method parameters. This allows for easier testing, as dependencies can be easily mocked or stubbed during unit testing.

How to Implement Dependency Injection in C

To implement dependency injection in C#, we need to follow a few steps:

  1. Identify the dependencies of the class: The first step is to identify the dependencies that the class requires to function properly. These dependencies can be other classes, interfaces, or services.

  2. Create interfaces for the dependencies: Once the dependencies are identified, it is recommended to create interfaces for them. This allows for easier mocking and stubbing during unit testing.

  3. Modify the class to accept dependencies through its constructor: The next step is to modify the class to accept its dependencies through its constructor. This is known as constructor injection. By doing this, the class becomes more flexible and easier to test.

  4. Use a dependency injection container: To manage the creation and resolution of dependencies, we can use a dependency injection container. A container is responsible for creating instances of classes and resolving their dependencies.

Example: Unit Testing a Class with Dependency Injection

Let’s consider an example where we have a MainClass that depends on a logger and a database. Here’s how we can refactor the MainClass to follow the explicit dependencies principle:

public class MainClass : IMainClass  
{
    private readonly ILogger logger;
    private readonly IDatabase db;

    public MainClass(ILogger logger, IDatabase db) 
    {
        this.logger = logger;  
        this.db = db;
    }

    public void AddDetails(Data data) 
    {
        // do some business operations 
        db.Add(data);
        logger.Information("added");
    }
}

In the above code, we have modified the MainClass to accept its dependencies (ILogger and IDatabase) through its constructor.

To test the MainClass, we need to mock the necessary dependencies. Here’s an example of how we can write a unit test for the AddDetails method:

[TestClass]
public class MainClassTests 
{    
    [TestMethod]
    public void Should_AddDetails_To_Database() 
    {
        // Arrange
        var mockDb = new Mock<IDatabase>();
        var data = new Data();
        var mainClass = new MainClass(Mock.Of<ILogger>(), mockDb.Object);

        // Act
        mainClass.AddDetails(data);

        // Assert    
        mockDb.Verify(_ => _.Add(data), Times.Once);
    }
}

In the above test, we create a mock object for the IDatabase dependency and pass it to the MainClass constructor along with a mocked ILogger object. We then call the AddDetails method and assert that the Add method of the IDatabase dependency is called once with the correct data.

Conclusion

In this article, we have explored how to unit test code that uses dependency injection in C#. By following the steps outlined above, we can effectively manage dependencies and write testable code. The use of dependency injection allows for easier mocking and stubbing of dependencies during unit testing, resulting in more reliable and maintainable code.

Categories C#

Related Posts

C# Triple Double Quotes: What are they and how to use them?

In C# programming language, triple double quotes (“””) are a special syntax known as raw string literals. They provide a convenient way to work with strings that contain quotes or embedded language strings like JSON, XML, HTML, SQL, Regex, and others. Raw string literals eliminate the need for escaping characters, making it easier to write ...

Read more

Best Practices in Using a Lock in C#

What is a Lock? A lock in C# is implemented using the lock keyword, which ensures that only one thread can enter a specific section of code at a time. When a thread encounters a lock statement, it attempts to acquire a lock on the specified object. If the lock is already held by another ...

Read more

Usage of ‘&’ versus ‘&&’ in C#

‘&’ Operator The ‘&’ operator in C# is a bitwise AND operator. It operates at the bit level, meaning that it performs the AND operation on each corresponding pair of bits in the operands. This operator is commonly used when working with binary data or performing low-level bit manipulation. For example, consider the following code ...

Read more

How to Add a Badge to a C# WinForms Control

Have you ever wanted to add a badge to a C# WinForms control? Maybe you want to display a notification count on a button or indicate the status of a control. In this article, I will show you how to easily add a badge to a C# WinForms control using a static Adorner class. What ...

Read more

Leave a Comment