Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Pragmatic Test-Driven Development in C# and .NET

You're reading from  Pragmatic Test-Driven Development in C# and .NET

Product type Book
Published in Sep 2022
Publisher Packt
ISBN-13 9781803230191
Pages 372 pages
Edition 1st Edition
Languages
Author (1):
Adam Tibi Adam Tibi
Profile icon Adam Tibi

Table of Contents (21) Chapters

Preface 1. Part 1: Getting Started and the Basics of TDD
2. Chapter 1: Writing Your First TDD Implementation 3. Chapter 2: Understanding Dependency Injection by Example 4. Chapter 3: Getting Started with Unit Testing 5. Chapter 4: Real Unit Testing with Test Doubles 6. Chapter 5: Test-Driven Development Explained 7. Chapter 6: The FIRSTHAND Guidelines of TDD 8. Part 2: Building an Application with TDD
9. Chapter 7: A Pragmatic View of Domain-Driven Design 10. Chapter 8: Designing an Appointment Booking App 11. Chapter 9: Building an Appointment Booking App with Entity Framework and Relational DB 12. Chapter 10: Building an App with Repositories and Document DB 13. Part 3: Applying TDD to Your Projects
14. Chapter 11: Implementing Continuous Integration with GitHub Actions 15. Chapter 12: Dealing with Brownfield Projects 16. Chapter 13: The Intricacies of Rolling Out TDD 17. Index 18. Other Books You May Enjoy Appendix 1: Commonly Used Libraries with Unit Tests 1. Appendix 2: Advanced Mocking Scenarios

Understanding Dependency Injection by Example

Dependency injection (DI) is a software design pattern that exists in every modern architecture. However, you may wonder how this pattern found its way into the second chapter of a test-driven development (TDD)-focused book.

DI is a pattern that has several benefits that we are going to discover throughout the book, though the core benefit is that DI opens an application for unit testing. We cannot exercise unit testing without a solid understanding of this pattern, and if we cannot unit test, by virtue, we cannot practice TDD. Considering this, DI understanding forms the foundation of Section 1, Getting Started and Basics, and Part 2, Building an Application with TDD, which explains the early introduction.

We will build an application and then modify it to support DI while learning the concepts, but the ideas in this chapter will be repeated and exercised throughout this book.

In this chapter, you will be exploring these topics...

Technical requirements

The code for this chapter can be found at the following GitHub repository:

https://github.com/PacktPublishing/Pragmatic-Test-Driven-Development-in-C-Sharp-and-.NET/tree/main/ch02

There, you will find four directories. Each one will be a snapshot of our progress.

The WFA

Throughout this chapter, we will be using an ASP.NET Web API application in our learning process. We will be refactoring all the code in this application to enable DI. Then, in Chapter 3, Getting Started with Unit Testing, we will apply unit tests on the refactored application.

When a new ASP.NET Web API application is created, it comes with a sample random weather forecaster. The application in this chapter will build on top of the original weather sample and will add a real weather forecasting capability to the existing random one. We will creatively call our application the WFA.

The first step is going to be creating a WFA application and making sure it is running.

Creating a sample weather forecaster

To create a sample application, navigate your console to the directory where you want to create this application and execute the following commands:

md UqsWeather
cd UqsWeather
dotnet new sln
dotnet new webapi -o Uqs.Weather -f net6.0
dotnet sln add Uqs.Weather...

Understanding dependency

If your code does something useful, chances are your code depends on other code or another component, which in turn depends on another component. A clear understanding of the dependency terminology should give you a better grasp of unit testing and will definitely aid in having clearer conversations with your colleagues.

The plan in this section is to familiarize you with the concept of dependency, which should make understanding the DI pattern easier. Understanding dependency and DI are prerequisites for writing any serious unit testing. Next, we will explore what dependencies are, though when it comes to unit testing, we don’t care for all dependencies, so we will define what a relevant dependency is.

Before we dive into dependencies, let’s first define abstraction types and concrete types.

Abstractions and concrete types

To have you and me on the same channel, I will define the terminology to be used.

A concrete class is a class...

Introducing DI

When I first learned how to do DI in code, I had a euphoria as if I had discovered a secret in software engineering; it is like code magic. We have been exploring dependencies in the previous sections and now, we are about to discover injecting these dependencies into our classes. The next step is explaining what DI is and using practical samples from the WFA application to make sure you are experimenting with a variety of scenarios. The best way to introduce DI is with a familiar example.

First example of DI

DI is all over any modern .NET code. In fact, we have one example right here in the ASP.NET template code:

public WeatherForecastController(
    ILogger<WeatherForecastController> logger) 
{
    _logger = logger;

The logger object, which is a dependency, is injected into the controller when a new instance of the controller is created. There is nowhere in the controller that we are instantiating the logger...

Using DI containers

A DI container is a library that injects a service into the client. A DI container provides extra functionality other than injecting dependencies, such as the following:

  • Registering the classes that need to be injected (registering the services)
  • Implementing how the services need to be instantiated
  • Instantiating what has already been registered
  • Managing the created service lifetime

Let’s clarify a DI container role with an example from the previous code. We have the logger service being injected, but who is responsible for this?

There is a DI container called Microsoft.Extensions.DependencyInjection that will inject _logger. This happened in the first line of Program.cs, as illustrated here:

var builder = WebApplication.CreateBuilder(args);

This previous method call registers a default logger. Unfortunately, while we can see the code in the .NET source code, it is not obvious in our Program.cs source code. In fact, the...

Summary

This is a long chapter, I admit, but my defense is that it has plenty of examples to cover many real-life DI scenarios. Also, DI automatically encourages good software engineering practices, so we had to include the relevant practices. If you were to develop TDD-style, you would spend around 10% of your coding time doing DI-related tasks, and I hope this chapter did the right job and added to your knowledge.

DI is mainly used with unit tests, so without it, DI may feel less interesting. The next chapter, Getting Started with Unit Testing, will use the WFA application that we refactored here, and hopefully, you will appreciate further this design pattern.

Further reading

To learn more about the topics discussed in the chapter, you can refer to the following links:

lock icon The rest of the chapter is locked
You have been reading a chapter from
Pragmatic Test-Driven Development in C# and .NET
Published in: Sep 2022 Publisher: Packt ISBN-13: 9781803230191
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}