Skip to main content

From crappy to happy - dependency what, now?

Following the introduction on this series on a previous post, we will now talk about dependency injection and how it has the effect of allowing for more testable code. Sometimes when I talk about this concept it is difficult to explain the effect that applying it might have on the tests. For that reason I think it is better to demonstrate with a near-real-world situation.
Obviously, keep in mind this is not real code, so don't worry about the design or implementation details that don't contribute to the point being discussed.

The code


As you can see, it is simple. There's a class called ShipManager (what else?) that receives position updates for the ships. It keeps the last position reported from each ship and does some calculation to see how much the ship moved. It assigns some values to the update and finally it persists the final version of the update.

How do we start testing?

When you think about it, tests are dead simple. A test either passes or it doesn't. I'm going to focus in unit tests here, and we could use a lot of frameworks like NUnit, XUnit, etc. Sure, we can introduce the whole plethora of tools that exist at the whim of a single command, but what is the simplest thing we can do to test our code? Check if true or false!

Since I want to keep this minimal, the tests in this series will be a matter of asserting a few conditions and printing true or false. This is not production code, but it provides a low barrier of entry for everyone.

Here is the example of a test:

Questions I want to answer with tests

Looking at how the code behaves, there are some immediate tests that we could write:
  • Is the distance calculated correctly from the previous position?
  • Does the manager persist the position?
  • Does the manager correctly calculate the expiration date for the position?
I will answer the first one, but after that I think the way to answer the other ones should be easy to understand.

 Why is the code not testable? 

There are multiple kinds of tests. We will focus on unit tests. These kinds of tests tend to be small, isolated and test a single behavior only.

I am instantiating the ShipPersistenceService and DistanceCalculator in the constructor of ShipManager on purpose. This makes it very difficult to build a unit test that tests a behavior in isolation, because then the ShipPersistenceService would need to have a database - or other persistence medium - set up in order to run the test. Also, how would I be able to get the distance that the calculator returned? Maybe use the fact that it mutates the update itself? That's crappy, but this kind of problem comes up very often in codebases. Here is the test that we will make possible:


Notice that both ShipPersistenceService and DistanceCalculator are used by the ShipManager in the PositionReceived method, so we could say that ShipManager depends on them to do the job. These two classes are dependencies that are being created in the constructor, but doing that is preventing us from isolating the ShipManager logic from it's dependencies.

Wouldn't it be good if we could just swap in fake dependencies? Then when we run the tests we wouldn't have to deal with the database. What if we could... like... inject dependencies? Yeah, that's an incredibly original idea. So we make a simple change:

Now we are using proper Dependency Injection. Notice that this does not yet achieve our objective, but we now are required to pass the dependencies as a parameter when creating a ShipManager in the test. We have control of those dependencies in the test, but not yet how they behave. We can easily change that using inheritance by marking the methods as virtual and then overriding the behavior in a test implementation that we then inject. And thus is born the mock. And what are mocks? They are fake implementations of the dependencies and serve the sole purpose of helping us testing. Here are the mocks for this case:



Notice that the mocks add a little something of their own. The ShipPersistenceServiceMock is recording the last ShipPositionUpdate it was called with. This will allow us to read it in the test. The DistanceCalculatorMock allows us to set the DistanceToReturn which is returned to the ShipManager. Let's see how to use these new capabilities for the test:


The fact that we can simply set the values we want the methods to return and also record the parameters is a really nice property we will be using A LOT. Almost every single unit test makes use of these features.

Who creates the dependencies now?

Since we are moving towards dependency injection now, who is responsible for creating he dependencies for each class? That is the topic for a whole other post, but the basic answer is: not the class that depends on them. You want to move the instantiation up. Once you start using this pattern you would normally start using in Inversion of Control Containers such as Unity or Ninject. There you can define the graph of your dependencies and assign scopes to each class. That is widely out of scope though.

For the tests, I find it better to just create the dependencies by hand and inject directly. This allows for easy to read tests that are also self contained without messing with IOC containers. Remember, your unit tests should be dead simple without too much of a hassle to run.

Recap

We applied the concept of dependency injection to code that had some dependencies. Coupled with some minor changes and the creation of mock objects, we were able to transform untestable code into testable. This technique is generally easy to implement, but on real code some issues will arise because the dependency graph is much more complex.

As for the way of using mocks, there are a lot of ways of doing this. Given the small context of the article, using inheritance was the easiest one to demonstrate. The most common way is to define interfaces for your dependencies and then depend on those interfaces instead of depending on the classes directly. You would then register these interfaces with your IOC container and define which specific type should be injected.

So this is it for this article on the From crappy to Happy series. Next up we will be dealing with a very common problem: that DateTime.UtcNow that I ignored can have some weird effects on the tests!

Comments

Popular posts from this blog

The repository's repository

Ever since I started delving into architecture,  and specifically service oriented architecture, there has been one matter where opinions get divided. Let me state the problem first, and then take a look at both sides of the barricade. Given that your service layer needs to access persistent storage, how do you model that layer? It is almost common knowledge what to do here: use the Repository design pattern. So we look at the pattern and decide that it seems simple enough! Let's implement the shit out of it! Now, let's say that you will use an ORM - here comes trouble. Specifically we're using EF, but we could be talking about NHibernate or really any other. The real divisive theme is this question: should you be using the repository pattern at all when you use an ORM? I'll flat out say it: I don't think you should... except with good reason. So, sharpen your swords, pray to your gods and come with me to fight this war... or maybe stay in the couch?

The evolution of C# - Part III - C# 2.0 - Iterators

It's been a while since i wrote the last post, but i did not forget my purpose of creating a series that shows the evolution of C#. Today i came here to talk about one of the most useful features of C#, even if you dont know you're using it. Let's talk about iterators ! What is an iterator? For those of you who didn't read about the iterator pattern somewhere in the internet or in the "Gang of Four" book, you can read a description  here . The iterator is a class/object/whatever which knows how to traverse a structure. So, if you have a list or collection of objects, an iterator would have the knowledge of how to traverse that collection and access each element that it contains. The iterator is a well known design pattern and is behind many of the wonderful that we have nowadays in .NET (Linq comes to mind). Why is it a feature? Truth be told, an iterator is a concept well known way before .NET even existed. Being an OO Design Pattern, the iterator has

My simplest and most useful type

I have been doing some introspection on the way I write code to find ways that I need to improve. I consider this a task that one must do periodically so that we keep organized. There is a very, very simple problem that occurs in every application I know: How to return the results of an operation to the user? I've seen many implementations. Some return strings, some throw exceptions, some use out parameters, reuse the domain classes and have extra properties in there, etc. There is a myriad of ways of accomplishing this. This is the one I use. I don't like throwing exceptions. There are certainly cases where you have no choice, but I always avoid that. Throughout my architectures there is a single prevalent type that hasn't changed for years now, and I consider that a sign of stability. It is so simple, yet so useful everywhere. The name may shock you, take a look: Yes, this is it. Take a moment to compose yourself. Mind you, this is used everywhere , in every