who will write unit test cases - CoursesEssaydatesCom

who will write unit test cases

/ DevOps Zone

Over a million developers have joined DZone.
Log In / Sign Up

  • node.title


    by node.authors[0].realName



  • totalResults search results

  • Refcardz
  • Guides
  • Zones
  • Jobs
  • |
  • Agile

  • AI

  • Big Data

  • Cloud

  • Database

  • DevOps

  • Integration

  • IoT

  • Java

  • Microservices

  • Open Source

  • Performance

  • Security

  • Web Dev



Let’s be friends:

9 Reasons Why a Developer Wouldn’t Write Unit Tests

DZone’s Guide to

9 Reasons Why a Developer Wouldn’t Write Unit Tests

Unit tests provide quick feedback on code, can speed up the release pipeline, and much more. Why would a developer not want to write unit tests at all?


Joe Wolf


Dec. 12, 16


Free Resource

Like (16)

Comment (8)




  • Edit
  • Delete
  • articles[0].isLocked
    ? ‘Enable’ : ‘Disable’ comments
  • articles[0].isLimited ? ‘Remove comment limits’ : ‘Enable moderated comments’

Join the DZone community and get the full member experience.

Join For Free

Learn more  about how CareerBuilder was able to resolve customer issues 5x faster by using Scalyr, the fastest log management tool on the market. 

Unit tests are a great way to get quick feedback about your code. They’re like an extension of the compiler that’s business logic-aware. A comprehensive suite of unit tests can prevent the introduction of stupid bugs, can speed up your release pipeline, and are a boon when you or some other developer has to make a change to code you’ve written long ago. The maturity and ubiquity of JUnit and supporting tooling have made the barrier to unit test entry extremely low. Heck, you have to explicitly tell Maven not to run unit tests .

With all of these benefits and conveniences, why would a developer not want to write unit tests? Forget TDD, even; I’m talking about not writing unit tests at all.

Here are my theories.

1. You’re a Body Shop Developer

Perhaps there is a better term for this, but I believe there is a class of developers who are in the gig solely to earn a paycheck. They’re the types that just do what they’re told; no more, no less, and usually without any reservations. Management wants to target JavaEE 5. "Sounds good. I know JSP." All developers must use the same IDE: Rational Software Architect. "Sure thing, boss." Our coding standards require Hungarian notation. "No problem." If the developers are not required to write unit tests, they won’t do it; neither will they volunteer to write unit tests because that would just be extra work the client would get for free.

2. You Don’t Know Any Better

Developers just starting out may be unaware that unit testing is even a thing. (Perhaps IT education has improved since I went to college; all I can say is that I was able to earn a B.S. in Computer Science without knowing anything about unit testing.) This is where a strong, experienced development team lead is important; somebody who can establish the code of conduct for the team with rules like, "If you break the CI build, don’t leave the office until it’s fixed," "No SNAPSHOT dependencies in the POMs," and "Don’t submit a PR without unit tests."

3. You Write Terrible Code

Some developers have no qualms writing low-level JDBC code inside a Servlet. To them, separation of concerns and high cohesion are just highfalutin computer science concepts. My guess is that these kinds of developers rarely write unit tests because their code is essentially untestable. The thought of just mocking up all of the necessary dependencies is daunting enough to make them abandon the idea altogether. Even if you do have some respect for those highfalutin computer science concepts, you may still have coding habits that negatively impact the testability of your code, resulting in a diminished regard for unit testing. Field injection , anyone?

4. You Suffer From Hubris

Admittedly, I find myself fighting against this at times, especially when I’m working solo. I begin to consider my code well-designed and simple enough to make unit tests largely unnecessary. Of course, when I remind myself that I’m a professional and begrudgingly crank some tests out, I inevitably find a bug or discover some important design feedback. The best way to deal with excessive pride, in my opinion, is to work on a team of comparably talented peers and to keep code quality metrics as transparent as possible. It’s hard to believe you’re a superstar when the CTO’s dashboard shows that your project has the lowest code coverage in the company.

5. You’re a Cowboy or Consultant

I borrowed this phrasing from John Berryman . Cowboys tend to gain their reputation by quickly solving urgent problems, often at the expense of software development rigor. Consultants, particularly those brought in to establish software architectures at the onset of development efforts, will produce prototype-quality code. There are few tests (if any) because their purpose is to prove out an application architecture rather than to produce fully functioning software. In both cases, unit testing is not perceived to add value to the tasks at hand. Whether or not their perception is correct is debatable, but as someone who has acted in both a cowboy and consultant role, I can attest that the perception is real.

6. Your Spirits Are Crushed

Maybe the code you’re working on has no chance of making it to production. Maybe your userbase is just a handful of jerks. Perhaps your company’s vision isn’t aligned with your own, and every line of code you write is a reminder of other code you could be writing instead. Regardless of the reason, if you’re apathetic or resentful to code you’re working on, you probably won’t care enough to unit test it. Here’s an idea: Use the time you should be writing unit tests on looking for a new job.

7. Your Corporate Culture Does Not Value Unit Testing

Project-driven organizations tend to disregard the importance code quality and maintainability because completing projects on time and within budget is the primary focus. Project management doesn’t care that much if the project yields well-written code with a comprehensive suite of automated tests. Those are longer-term benefits that won’t be realized until well after the project is over and management has shifted attention to other projects.

8. You Inherited a Convoluted Codebase

From my experience, maintenance developers for large, complex, terribly written codebases tend to do little unit testing. Some of this could be attributable to crushed spirits or perhaps because maintenance development teams tend to be staffed with more junior developers or body shop personalities. It could also be attributable to the overall effort vs. value imbalance. Writing unit tests for the codebase would require such extensive refactoring that developers refuse to undertake the task ("Please, just let us rewrite the thing from scratch!"). Similarly, management could be unwilling to invest in work required to expand the unit test suite, money-wise or time-wise. The latter goes back to a project-driven culture’s focus on short-term objectives at the expense of investing in longer-term code maintainability. This very same focus is probably what led to the creation of the convoluted code base.

9. Your Corporate Culture Unwittingly Disincentivizes Unit Testing

A company that values unit testing may actually discourage it if its incentive structures are out of alignment with those values. One example could be a project-driven company that superficially enforces unit testing, like by only checking if developers complete their mandatory "Write Unit Tests" task for every user story, but strictly enforces that project deadlines and scope are met. Another example could be a company gives a bonus to the developer who fixes the most bugs that month, regardless of who was responsible for introducing the bugs. This sort of policy encourages some developers to release risky code into production as it creates opportunities to increase their bug fix tally.


These are all potentially valid reasons for not writing unit tests, but they’re not necessarily valid excuses. I’ve been negligent in my unit testing for too long; it’s time for me to take it more seriously.

Find out more about how Scalyr built a proprietary database that does not use text indexing for their log management tool.

Like This Article? Read More From DZone

Implementing Unit Testing: Goals

Implementing Unit Testing: Leading Indicators (Part 1)

Implementing Unit Testing: Outcomes

Free DZone Refcard

Introduction to DevSecOps

unit testing
software development

Like (16)

Comment (8)




  • Edit
  • Delete
  • articles[0].isLocked
    ? ‘Enable’ : ‘Disable’ comments
  • articles[0].isLimited ? ‘Remove comment limits’ : ‘Enable moderated comments’

Opinions expressed by DZone contributors are their own.

DevOps Partner Resources

DevSecOps Reference Architectures

4 Steps to an Effective DevSecOps Infrastructure. Download the guide now.

IT Alerting Is Just the Beginning: Identify, Notify, & Empower People to Take Action. Sign up for free now.

The Transformative Technologies Driving DevOps

How InfluxDB outperforms Cassandra by 20x for Time Series Data Management

10 Things to Get Right for Successful DevSecOps

The DevOps 2.0 ToolKit brought to you by Cloudbees

Examining the Features of a Good Log File Viewer

What To Look for in a Logging Framework

Automate Security in Your DevOps Pipeline

Choosing Among Log Management Tools

Avoid DevOps Mayhem. 4 Ways to Improve Your DevOps Testing.

DevOps Partner Resources

DevSecOps Reference Architectures

4 Steps to an Effective DevSecOps Infrastructure. Download the guide now.

IT Alerting Is Just the Beginning: Identify, Notify, & Empower People to Take Action. Sign up for free now.

The Transformative Technologies Driving DevOps


  • node.blurb

    Free node.type






by parent.author

· parent.articleDate date:’MMM. dd, yyyy’
· parent.portal.name Zone

parent.views ViewsClicks

  • Edit
  • Delete
  • parent.isLocked ? ‘Enable’ : ‘Disable’ comments
  • parent.isLimited ? ‘Remove comment limits’ : ‘Enable moderated comments’

Hiring? Toptal handpicks top QA engineers to suit your needs.

Unit Tests, How to Write Testable Code and Why it Matters

View all articles

Small 1dcf9844a6e3755a5f48c3e39836a061

by Sergey Kolodiy – Freelance Software Engineer
@ Toptal

#BestPractices #DesignPatterns #OOP #QA #Testing
  • 0shares

Unit testing is an essential instrument in the toolbox of any serious software developer . However, it can sometimes be quite difficult to write a good unit test for a particular piece of code. Having difficulty testing their own or someone else’s code, developers often think that their struggles are caused by a lack of some fundamental testing knowledge or secret unit testing techniques.

In this unit testing tutorial, I intend to demonstrate that unit tests are quite easy; the real problems that complicate unit testing, and introduce expensive complexity, are a result of poorly-designed, untestable code. We will discuss what makes code hard to test, which anti-patterns and bad practices we should avoid to improve testability, and what other benefits we can achieve by writing testable code. We will see that writing unit tests and generating testable code is not just about making testing less troublesome, but about making the code itself more robust, and easier to maintain.

Unit testing tutorial: cover illustration

What is Unit Testing?

Essentially, a unit test is a method that instantiates a small portion of our application and verifies its behavior independently from other parts. A typical unit test contains 3 phases: First, it initializes a small piece of an application it wants to test (also known as the system under test, or SUT), then it applies some stimulus to the system under test (usually by calling a method on it), and finally, it observes the resulting behavior. If the observed behavior is consistent with the expectations, the unit test passes, otherwise, it fails, indicating that there is a problem somewhere in the system under test. These three unit test phases are also known as Arrange, Act and Assert, or simply AAA.

A unit test can verify different behavioral aspects of the system under test, but most likely it will fall into one of the following two categories: state-based or interaction-based. Verifying that the system under test produces correct results, or that its resulting state is correct, is called state-based unit testing, while verifying that it properly invokes certain methods is called interaction-based unit testing.

As a metaphor for proper software unit testing, imagine a mad scientist who wants to build some supernatural chimera , with frog legs, octopus tentacles, bird wings, and a dog’s head. (This metaphor is pretty close to what programmers actually do at work). How would that scientist make sure that every part (or unit) he picked actually works? Well, he can take, let’s say, a single frog’s leg, apply an electrical stimulus to it, and check for proper muscle contraction. What he is doing is essentially the same Arrange-Act-Assert steps of the unit test; the only difference is that, in this case, unit refers to a physical object, not to an abstract object we build our programs from.

what is unit testing: illustration

I will use C# for all examples in this article, but the concepts described apply to all object-oriented programming languages.

An example of a simple unit test could look like this:

public void IsPalindrome_ForPalindromeString_ReturnsTrue() // In the Arrange phase, we create and set up a system under test. // A system under test could be a method, a single object, or a graph of connected objects. // It is OK to have an empty Arrange phase, for example if we are testing a static method - // in this case SUT already exists in a static form and we don't have to initialize anything explicitly. PalindromeDetector detector = new PalindromeDetector(); // The Act phase is where we poke the system under test, usually by invoking a method. // If this method returns something back to us, we want to collect the result to ensure it was correct. // Or, if method doesn't return anything, we want to check whether it produced the expected side effects. bool isPalindrome = detector.IsPalindrome("kayak"); // The Assert phase makes our unit test pass or fail. // Here we check that the method's behavior is consistent with expectations. Assert.IsTrue(isPalindrome);

Unit Test vs. Integration Test

Another important thing to consider is the difference between unit testing and integration testing.

The purpose of a unit test in software engineering is to verify the behavior of a relatively small piece of software, independently from other parts. Unit tests are narrow in scope, and allow us to cover all cases, ensuring that every single part works correctly.

On the other hand, integration tests demonstrate that different parts of a system work together in the real-life environment. They validate complex scenarios (we can think of integration tests as a user performing some high-level operation within our system), and usually require external resources, like databases or web servers, to be present.

Let’s go back to our mad scientist metaphor, and suppose that he has successfully combined all the parts of the chimera. He wants to perform an integration test of the resulting creature, making sure that it can, let’s say, walk on different types of terrain. First of all, the scientist must emulate an environment for the creature to walk on. Then, he throws the creature into that environment and pokes it with a stick, observing if it walks and moves as designed. After finishing a test, the mad scientist cleans up all the dirt, sand and rocks that are now scattered in his lovely laboratory.

unit testing example illustration

Notice the significant difference between unit and integration tests: A unit test verifies the behavior of small part of the application, isolated from the environment and other parts, and is quite easy to implement, while an integration test covers interactions between different components, in the close-to-real-life environment, and requires more effort, including additional setup and teardown phases.

A reasonable combination of unit and integration tests ensures that every single unit works correctly, independently from others, and that all these units play nicely when integrated, giving us a high level of confidence that the whole system works as expected.

However, we must remember to always identify what kind of test we are implementing: a unit or an integration test. The difference can sometimes be deceiving. If we think we are writing a unit test to verify some subtle edge case in a business logic class, and realize that it requires external resources like web services or databases to be present, something is not right — essentially, we are using a sledgehammer to crack a nut. And that means bad design.

What Makes a Good Unit Test?

Before diving into the main part of this tutorial and writing unit tests, let’s quickly discuss the properties of a good unit test. Unit testing principles demand that a good test is:

  • Easy to write. Developers typically write lots of unit tests to cover different cases and aspects of the application’s behavior, so it should be easy to code all of those test routines without enormous effort.

  • Readable. The intent of a unit test should be clear. A good unit test tells a story about some behavioral aspect of our application, so it should be easy to understand which scenario is being tested and — if the test fails — easy to detect how to address the problem. With a good unit test, we can fix a bug without actually debugging the code!

  • Reliable. Unit tests should fail only if there’s a bug in the system under test. That seems pretty obvious, but programmers often run into an issue when their tests fail even when no bugs were introduced. For example, tests may pass when running one-by-one, but fail when running the whole test suite, or pass on our development machine and fail on the continuous integration server. These situations are indicative of a design flaw. Good unit tests should be reproducible and independent from external factors such as the environment or running order.

  • Fast. Developers write unit tests so they can repeatedly run them and check that no bugs have been introduced. If unit tests are slow, developers are more likely to skip running them on their own machines. One slow test won’t make a significant difference; add one thousand more and we’re surely stuck waiting for a while. Slow unit tests may also indicate that either the system under test, or the test itself, interacts with external systems, making it environment-dependent.

  • Truly unit, not integration. As we already discussed, unit and integration tests have different purposes. Both the unit test and the system under test should not access the network resources, databases, file system, etc., to eliminate the influence of external factors.

That’s it — there are no secrets to writing unit tests. However, there are some techniques that allow us to write testable code.

Testable and Untestable Code

Some code is written in such a way that it is hard, or even impossible, to write a good unit test for it. So, what makes code hard to test? Let’s review some anti-patterns, code smells, and bad practices that we should avoid when writing testable code.

Poisoning the Codebase with Non-Deterministic Factors

Let’s start with a simple example. Imagine that we are writing a program for a smart home microcontroller, and one of the requirements is to automatically turn on the light in the backyard if some motion is detected there during the evening or at night. We have started from the bottom up by implementing a method that returns a string representation of the approximate time of day (“Night”, “Morning”, “Afternoon” or “Evening”):

public static string GetTimeOfDay() DateTime time = DateTime.Now; if (time.Hour >= 0 && time.Hour < 6) return "Night"; if (time.Hour >= 6 && time.Hour < 12) return "Morning"; if (time.Hour >= 12 && time.Hour < 18) return "Afternoon"; return "Evening";

Essentially, this method reads the current system time and returns a result based on that value. So, what’s wrong with this code?

If we think about it from the unit testing perspective, we’ll see that it is not possible to write a proper state-based unit test for this method. DateTime.Now is, essentially, a hidden input, that will probably change during program execution or between test runs. Thus, subsequent calls to it will produce different results.

Such non-deterministic behavior makes it impossible to test the internal logic of the GetTimeOfDay() method without actually changing the system date and time. Let’s have a look at how such test would need to be implemented:

public void GetTimeOfDay_At6AM_ReturnsMorning() try // Setup: change system time to 6 AM ... // Arrange phase is empty: testing static method, nothing to initialize // Act string timeOfDay = GetTimeOfDay(); // Assert Assert.AreEqual("Morning", timeOfDay); finally // Teardown: roll system time back ... 

Tests like this would violate a lot of the rules discussed earlier. It would be expensive to write (because of the non-trivial setup and teardown logic), unreliable (it may fail even if there are no bugs in the system under test, due to system permission issues, for example), and not guaranteed to run fast. And, finally, this test would not actually be a unit test — it would be something between a unit and integration test, because it pretends to test a simple edge case but requires an environment to be set up in a particular way. The result is not worth the effort, huh?

Turns out that all these testability problems are caused by the low-quality GetTimeOfDay() API. In its current form, this method suffers from several issues:

  • It is tightly coupled to the concrete data source. It is not possible to reuse this method for processing date and time retrieved from other sources, or passed as an argument; the method works only with the date and time of the particular machine that executes the code. Tight coupling is the primary root of most testability problems.

  • It violates the Single Responsibility Principle (SRP). The method has multiple responsibilities; it consumes the information and also processes it. Another indicator of SRP violation is when a single class or method has more than one reason to change. From this perspective, the GetTimeOfDay() method could be changed either because of internal logic adjustments, or because the date and time source should be changed.

  • It lies about the information required to get its job done. Developers must read every line of the actual source code to understand what hidden inputs are used and where they come from. The method signature alone is not enough to understand the method’s behavior.

  • It is hard to predict and maintain. The behavior of a method that depends on a mutable global state cannot be predicted by merely reading the source code; it is necessary to take into account its current value, along with the whole sequence of events that could have changed it earlier. In a real-world application, trying to unravel all that stuff becomes a real headache.

After reviewing the API, let’s finally fix it! Fortunately, this is much easier than discussing all of its flaws — we just need to break the tightly coupled concerns.

Fixing the API: Introducing a Method Argument

The most obvious and easy way of fixing the API is by introducing a method argument:

public static string GetTimeOfDay(DateTime dateTime) if (dateTime.Hour >= 0 && dateTime.Hour < 6) return "Night"; if (dateTime.Hour >= 6 && dateTime.Hour < 12) return "Morning"; if (dateTime.Hour >= 12 && dateTime.Hour < 18) return "Noon"; return "Evening";

Now the method requires the caller to provide a DateTime argument, instead of secretly looking for this information by itself. From the unit testing perspective, this is great; the method is now deterministic (i.e., its return value fully depends on the input), so state-based testing is as easy as passing some DateTime value and checking the result:

public void GetTimeOfDay_For6AM_ReturnsMorning() // Arrange phase is empty: testing static method, nothing to initialize // Act string timeOfDay = GetTimeOfDay(new DateTime(2015, 12, 31, 06, 00, 00)); // Assert Assert.AreEqual("Morning", timeOfDay);

Notice that this simple refactor also solved all the API issues discussed earlier (tight coupling, SRP violation, unclear and hard to understand API) by introducing a clear seam between what data should be processed and how it should be done.

Excellent — the method is testable, but how about its clients? Now it is the caller’s responsibility to provide date and time to the GetTimeOfDay(DateTime dateTime) method, meaning that they could become untestable if we don’t pay enough attention. Let’s have a look how we can deal with that.

Fixing the Client API: Dependency Injection

Say we continue working on the smart home system, and implement the following client of the GetTimeOfDay(DateTime dateTime) method — the aforementioned smart home microcontroller code responsible for turning the light on or off, based on the time of day and the detection of motion:

public class SmartHomeController public DateTime LastMotionTime get; private set; public void ActuateLights(bool motionDetected) DateTime time = DateTime.Now; // Ouch! // Update the time of last motion. if (motionDetected) LastMotionTime = time; // If motion was detected in the evening or at night, turn the light on. string timeOfDay = GetTimeOfDay(time); if (motionDetected && (timeOfDay == "Evening" 

Ouch! We have the same kind of hidden DateTime.Now input problem — the only difference is that it is located on a little bit higher of an abstraction level. To solve this issue, we can introduce another argument, again delegating the responsibility of providing a DateTime value to the caller of a new method with signature ActuateLights(bool motionDetected, DateTime dateTime). But, instead of moving the problem a level higher in the call stack once more, let’s employ another technique that will allow us to keep both ActuateLights(bool motionDetected) method and its clients testable: Inversion of Control , or IoC.

Inversion of Control is a simple, but extremely useful, technique for decoupling code, and for unit testing in particular. (After all, keeping things loosely coupled is essential for being able to analyze them independently from each other.) The key point of IoC is to separate decision-making code (when to do something) from action code (what to do when something happens). This technique increases flexibility, makes our code more modular, and reduces coupling between components.

Inversion of Control can be implemented in a number of ways; let’s have a look at one particular example — Dependency Injection using a constructor — and how it can help in building a testable SmartHomeController API.

First, let’s create an IDateTimeProvider interface, containing a method signature for obtaining some date and time:

public interface IDateTimeProvider DateTime GetDateTime();

Then, make SmartHomeController reference an IDateTimeProvider implementation, and delegate it the responsibility of obtaining date and time:

public class SmartHomeController private readonly IDateTimeProvider _dateTimeProvider; // Dependency public SmartHomeController(IDateTimeProvider dateTimeProvider) // Inject required dependency in the constructor. _dateTimeProvider = dateTimeProvider; public void ActuateLights(bool motionDetected) DateTime time = _dateTimeProvider.GetDateTime(); // Delegating the responsibility // Remaining light control logic goes here... 

Now we can see why Inversion of Control is so called: the control of what mechanism to use for reading date and time was inverted, and now belongs to the client of SmartHomeController, not SmartHomeController itself. Thereby, the execution of the ActuateLights(bool motionDetected) method fully depends on two things that can be easily managed from the outside: the motionDetected argument, and a concrete implementation of IDateTimeProvider, passed into a SmartHomeController constructor.

Why is this significant for unit testing? It means that different IDateTimeProvider implementations can be used in production code and unit test code. In the production environment, some real-life implementation will be injected (e.g., one that reads actual system time). In the unit test, however, we can inject a “fake” implementation that returns a constant or predefined DateTime value suitable for testing the particular scenario.

A fake implementation of IDateTimeProvider could look like this:

public class FakeDateTimeProvider : IDateTimeProvider public DateTime ReturnValue get; set; public DateTime GetDateTime() return ReturnValue; public FakeDateTimeProvider(DateTime returnValue) ReturnValue = returnValue; 

With the help of this class, it is possible to isolate SmartHomeController from non-deterministic factors and perform a state-based unit test. Let’s verify that, if motion was detected, the time of that motion is recorded in the LastMotionTime property:

void ActuateLights_MotionDetected_SavesTimeOfMotion() // Arrange var controller = new SmartHomeController(new FakeDateTimeProvider(new DateTime(2015, 12, 31, 23, 59, 59))); // Act controller.ActuateLights(true); // Assert Assert.AreEqual(new DateTime(2015, 12, 31, 23, 59, 59), controller.LastMotionTime);

Great! A test like this was not possible before refactoring. Now that we’ve eliminated non-deterministic factors and verified the state-based scenario, do you think SmartHomeController is fully testable?

Poisoning the Codebase with Side Effects

Despite the fact that we solved the problems caused by the non-deterministic hidden input, and we were able to test certain functionality, the code (or, at least, some of it) is still untestable!

Let’s review the following part of the ActuateLights(bool motionDetected) method responsible for turning the light on or off:

// If motion was detected in the evening or at night, turn the light on.
if (motionDetected && (timeOfDay == "Evening" || timeOfDay == "Night")) BackyardLightSwitcher.Instance.TurnOn();
// If no motion was detected for one minute, or if it is morning or day, turn the light off.
else if (time.Subtract(LastMotionTime) > TimeSpan.FromMinutes(1) || (timeOfDay == "Morning" || timeOfDay == "Noon")) BackyardLightSwitcher.Instance.TurnOff();

As we can see, SmartHomeController delegates the responsibility of turning the light on or off to a BackyardLightSwitcher object, which implements a Singleton pattern . What’s wrong with this design?

To fully unit test the ActuateLights(bool motionDetected) method, we should perform interaction-based testing in addition to the state-based testing; that is, we should ensure that methods for turning the light on or off are called if, and only if, appropriate conditions are met. Unfortunately, the current design does not allow us to do that: the TurnOn() and TurnOff() methods of BackyardLightSwitcher trigger some state changes in the system, or, in other words, produce side effects . The only way to verify that these methods were called is to check whether their corresponding side effects actually happened or not, which could be painful.

Indeed, let’s suppose that the motion sensor, backyard lantern, and smart home microcontroller are connected into an Internet of Things network and communicate using some wireless protocol. In this case, a unit test can make an attempt to receive and analyze that network traffic. Or, if the hardware components are connected with a wire, the unit test can check whether the voltage was applied to the appropriate electrical circuit. Or, after all, it can check that the light actually turned on or off using an additional light sensor.

As we can see, unit testing side-effecting methods could be as hard as unit testing non-deterministic ones, and may even be impossible. Any attempt will lead to problems similar to those we’ve already seen. The resulting test will be hard to implement, unreliable, potentially slow, and not-really-unit. And, after all that, the flashing of the light every time we run the test suite will eventually drive us crazy!

Again, all these testability problems are caused by the bad API, not the developer’s ability to write unit tests. No matter how exactly light control is implemented, the SmartHomeController API suffers from these already-familiar issues:

  • It is tightly coupled to the concrete implementation. The API relies on the hard-coded, concrete instance of BackyardLightSwitcher. It is not possible to reuse the ActuateLights(bool motionDetected) method to switch any light other than the one in the backyard.

  • It violates the Single Responsibility Principle. The API has two reasons to change: First, changes to the internal logic (such as choosing to make the light turn on only at night, but not in the evening) and second, if the light-switching mechanism is replaced with another one.

  • It lies about its dependencies. There is no way for developers to know that SmartHomeController depends on the hard-coded BackyardLightSwitcher component, other than digging into the source code.

  • It is hard to understand and maintain. What if the light refuses to turn on when the conditions are right? We could spend a lot of time trying to fix the SmartHomeController to no avail, only to realize that the problem was caused by a bug in the BackyardLightSwitcher (or, even funnier, a burned out lightbulb!).

The solution of both testability and low-quality API issues is, not surprisingly, to break tightly coupled components from each other. As with the previous example, employing Dependency Injection would solve these issues; just add an ILightSwitcher dependency to the SmartHomeController, delegate it the responsibility of flipping the light switch, and pass a fake, test-only ILightSwitcher implementation that will record whether the appropriate methods were called under the right conditions. However, instead of using Dependency Injection again, let’s review an interesting alternative approach for decoupling the responsibilities.

Fixing the API: Higher-Order Functions

This approach is an option in any object-oriented language that supports first-class functions . Let’s take advantage of C#’s functional features and make the ActuateLights(bool motionDetected) method accept two more arguments: a pair of Action delegates, pointing to methods that should be called to turn the light on and off. This solution will convert the method into a higher-order function :

public void ActuateLights(bool motionDetected, Action turnOn, Action turnOff) DateTime time = _dateTimeProvider.GetDateTime(); // Update the time of last motion. if (motionDetected) LastMotionTime = time; // If motion was detected in the evening or at night, turn the light on. string timeOfDay = GetTimeOfDay(time); if (motionDetected && (timeOfDay == "Evening" 

This is a more functional-flavored solution than the classic object-oriented Dependency Injection approach we’ve seen before; however, it lets us achieve the same result with less code, and more expressiveness, than Dependency Injection. It is no longer necessary to implement a class that conforms to an interface in order to supply SmartHomeController with the required functionality; instead, we can just pass a function definition. Higher-order functions can be thought of as another way of implementing Inversion of Control.

Now, to perform an interaction-based unit test of the resulting method, we can pass easily verifiable fake actions into it:

public void ActuateLights_MotionDetectedAtNight_TurnsOnTheLight() // Arrange: create a pair of actions that change boolean variable instead of really turning the light on or off. bool turnedOn = false; Action turnOn = () => turnedOn = true; Action turnOff = () => turnedOn = false; var controller = new SmartHomeController(new FakeDateTimeProvider(new DateTime(2015, 12, 31, 23, 59, 59))); // Act controller.ActuateLights(true, turnOn, turnOff); // Assert Assert.IsTrue(turnedOn);

Finally, we have made the SmartHomeController API fully testable, and we are able to perform both state-based and interaction-based unit tests for it. Again, notice that in addition to improved testability, introducing a seam between the decision-making and action code helped to solve the tight coupling problem, and led to a cleaner, reusable API.

Now, in order to achieve full unit test coverage, we can simply implement a bunch of similar-looking tests to validate all possible cases — not a big deal since unit tests are now quite easy to implement.

Impurity and Testability

Uncontrolled non-determinism and side effects are similar in their destructive effects on the codebase. When used carelessly, they lead to deceptive, hard to understand and maintain, tightly coupled, non-reusable, and untestable code.

On the other hand, methods that are both deterministic and side-effect-free are much easier to test, reason about, and reuse to build larger programs. In terms of functional programming, such methods are called pure functions . We’ll rarely have a problem unit testing a pure function; all we have to do is to pass some arguments and check the result for correctness. What really makes code untestable is hard-coded, impure factors that cannot be replaced, overridden, or abstracted away in some other way.

Impurity is toxic: if method Foo() depends on non-deterministic or side-effecting method Bar(), then Foo() becomes non-deterministic or side-effecting as well. Eventually, we may end up poisoning the entire codebase. Multiply all these problems by the size of a complex real-life application, and we’ll find ourselves encumbered with a hard to maintain codebase full of smells, anti-patterns, secret dependencies, and all sorts of ugly and unpleasant things.

unit testing example: illustration

However, impurity is inevitable; any real-life application must, at some point, read and manipulate state by interacting with the environment, databases, configuration files, web services, or other external systems. So instead of aiming to eliminate impurity altogether, it’s a good idea to limit these factors, avoid letting them poison your codebase, and break hard-coded dependencies as much as possible, in order to be able to analyze and unit test things independently.

Common Warning Signs of Hard to Test Code

Trouble writing tests? The problem’s not in your test suite. It’s in your code.

Finally, let’s review some common warning signs indicating that our code might be difficult to test.

Static Properties and Fields

Static properties and fields or, simply put, global state, can complicate code comprehension and testability, by hiding the information required for a method to get its job done, by introducing non-determinism, or by promoting extensive usage of side effects. Functions that read or modify mutable global state are inherently impure.

For example, it is hard to reason about the following code, which depends on a globally accessible property:

if (!SmartHomeSettings.CostSavingEnabled) _swimmingPoolController.HeatWater(); 

What if the HeatWater() method doesn’t get called when we are sure it should have been? Since any part of the application might have changed the CostSavingEnabled value, we must find and analyze all the places modifying that value in order to find out what’s wrong. Also, as we’ve already seen, it is not possible to set some static properties for testing purposes (e.g., DateTime.Now, or Environment.MachineName; they are read-only, but still non-deterministic).

On the other hand, immutable and deterministic global state is totally OK. In fact, there’s a more familiar name for this — a constant. Constant values like Math.PI do not introduce any non-determinism, and, since their values cannot be changed, do not allow any side effects:

double Circumference(double radius) return 2 * Math.PI * radius; // Still a pure function!


Essentially, the Singleton pattern is just another form of the global state. Singletons promote obscure APIs that lie about real dependencies and introduce unnecessarily tight coupling between components. They also violate the Single Responsibility Principle because, in addition to their primary duties, they control their own initialization and lifecycle.

Singletons can easily make unit tests order-dependent because they carry state around for the lifetime of the whole application or unit test suite. Have a look at the following example:

User GetUser(int userId) User user; if (UserCache.Instance.ContainsKey(userId)) user = UserCache.Instance[userId]; else user = _userService.LoadUser(userId); UserCache.Instance[userId] = user; return user;

In the example above, if a test for the cache-hit scenario runs first, it will add a new user to the cache, so a subsequent test of the cache-miss scenario may fail because it assumes that the cache is empty. To overcome this, we’ll have to write additional teardown code to clean the UserCache after each unit test run.

Using Singletons is a bad practice that can (and should) be avoided in most cases; however, it is important to distinguish between Singleton as a design pattern, and a single instance of an object. In the latter case, the responsibility of creating and maintaining a single instance lies with the application itself. Typically, this is handed with a factory or Dependency Injection container, which creates a single instance somewhere near the “top” of the application (i.e., closer to an application entry point) and then passes it to every object that needs it. This approach is absolutely correct, from both testability and API quality perspectives.

The new Operator

Newing up an instance of an object in order to get some job done introduces the same problem as the Singleton anti-pattern: unclear APIs with hidden dependencies, tight coupling, and poor testability.

For example, in order to test whether the following loop stops when a 404 status code is returned, the developer should set up a test web server:

using (var client = new HttpClient()) HttpResponseMessage response; do response = await client.GetAsync(uri); // Process the response and update the uri... while (response.StatusCode != HttpStatusCode.NotFound);

However, sometimes new is absolutely harmless: for example, it is OK to create simple entity objects:

var person = new Person("John", "Doe", new DateTime(1970, 12, 31));

It is also OK to create a small, temporary object that does not produce any side effects, except to modify their own state, and then return the result based on that state. In the following example, we don’t care whether Stack methods were called or not — we just check if the end result is correct:

string ReverseString(string input) // No need to do interaction-based testing and check that Stack methods were called or not; // The unit test just needs to ensure that the return value is correct (state-based testing). var stack = new Stack<char>(); foreach(var s in input) stack.Push(s); string result = string.Empty; while(stack.Count != 0) result += stack.Pop(); return result;

Static Methods

Static methods are another potential source of non-deterministic or side-effecting behavior. They can easily introduce tight coupling and make our code untestable.

For example, to verify the behavior of the following method, unit tests must manipulate environment variables and read the console output stream to ensure that the appropriate data was printed:

void CheckPathEnvironmentVariable() if (Environment.GetEnvironmentVariable("PATH") != null) Console.WriteLine("PATH environment variable exists."); else Console.WriteLine("PATH environment variable is not defined."); 

However, pure static functions are OK: any combination of them will still be a pure function. For example:

double Hypotenuse(double side1, double side2) return Math.Sqrt(Math.Pow(side1, 2) + Math.Pow(side2, 2)); 

Benefits of Unit Testing

Obviously, writing testable code requires some discipline, concentration, and extra effort. But software development is a complex mental activity anyway, and we should always be careful, and avoid recklessly throwing together new code from the top of our heads.

As a reward, we’ll end up with clean, easy-to-maintain, loosely coupled, and reusable APIs, that won’t damage developers’ brains when they try to understand it. After all, the ultimate advantage of testable code is not only the testability itself, but the ability to easily understand, maintain and extend that code as well.

Understanding the Basics

What is unit testing?

Unit testing is a method that instantiates a small part of our code and verifies its behavior independently from other parts of the project.

How to do unit testing and what does it entail?

A unit test typically features three different phases: Arrange, Act, and Assert (sometimes referred to as AAA). For a unit test to be successful, the resulting behavior in all three phases must be in line with expectations.

What is integration testing?

Integration testing focuses on testing and observing different software modules as a group. It is typically performed after unit testing is complete and precedes validation testing.

About the author

Sergey Kolodiy

View full profile »
Hire the Author
Sergey Kolodiy, Russia

member since September 25, 2014
Visual Studio ASP.NET MVC C# ASP.NET Web API .NET +   more
Sergey is a software engineer with extensive development experience in the .NET technology stack, with strong architecture and coding skills. He loves to work on complex and business-critical tasks with full involvement, high productivity, and great enjoyment. He is a big fan of clean, testable, and maintainable code and has worked for a number of successful projects ranging from small startups to complex enterprise applications. [click to continue…]
Hiring? Meet the Top 10 Freelance QA Engineers for Hire in August 2018


Ignacio Rodrigo
Really great article Sergey, thanks!
Awesome! Now let me go clean my craft as well…
Sergey Kolodiy
Hey Ignacio, thanks for your feedback! I’m really glad you like the article.
Paul Speranza
Beautiful article. Clear examples – passed on to entire dev team.
Loïc Ginoux
Thank you for this article, it’s always good to have a refresh on this principles. I’ll be interested to hear your opinion on a "testing challenge" I am facing. Soon I’ll have to put the tests suite of a web application up to date (~6-7 years old, a lots of leagcy code and a lot of mess!). It has been poorly tested, then tests were left abandoned and they are now never run. I will need to clean everything and add as much tests in a limited amount of time. How would you go with this sort of task? My though will be to:
– making first the test suite pass, it means trying to fix broken tests if possible or deleting tests that are too complicated to debug or badly written.
– as the app code is also not really suited for unit test, I will start by integration tests. It will at least secure the basic actions of the app and secure the key parts and day to day tasks that the app performs.
– If I have time left: I will dig into unit tests. I will do as much as I can, but it means refactoring the code that is poorly written and not suitable for unit test (and I know this is a dangerous task…)
– If I have no time left: when implementing new features and correcting bugs, I will allow some time to add tests and rewriting parts of the code that is involved in the feature or bug. This way, the app will slowly recover and be less prone to bugs.

Do you think this is the way to go? Would you approach this kind of app differently?

Thank you.

Sergey Kolodiy
Thanks for your feedback Loïc!

From my point of view, it depends on how exactly you want to approach this task. If your goal is to completely refactor, it doesn’t make much sense to fix existing unit tests and create new ones for the legacy code, because units themselves are likely to be redesigned. On the other hand, integration tests (if they are agnostic of internal API implementation) would certainly be helpful: at least, they’ll give you some confidence that certain scenarios are still correct.

So, your approach is absolutely correct and I don’t have much to add to it. Essentially, projects that have huge amount of technical debt don’t leave you much options to choose from: you should either allocate a lot of time to refactor everything and make it clean (which is quite risky, hard to estimate and not always possible), or you should refactor existing code step-by-step while implementing new features, fixing bugs or performing a code reviews.

Actually, I highly discourage writing unit tests that will not be used <strong>extensively</strong> to constantly prove that code is correct. Once broken, these tests may become legacy dead code themselves, so make sure that new unit and integration tests are used in your CI workflows and run after each commit. Good luck with your "testing challenge"! 🙂

Alexsandro Souza
Awesome article. Congratulations for the simple examples and perfect explanation.
Sergey Kolodiy
Thank you Alexsandro! It was quite challenging to explain all this stuff while keeping things simple and easy to understand, so I’m really glad you like it!
Kobi Halperin
Thanks for an interesting article, while I like the Unit testing part,
I don’t quite agree with your definition of Integration testing:
"integration tests demonstrate that different parts of a system work together in the real-life environment"

To me that’s more of a system testing (and many confuse the two),
Integration should focus on the interfaces (API, Protocols etc.) between the units,
verifying that data and commands is sent and received properly.
To Me – those real life scenario are the next level of system testing.

Sergey Kolodiy
Hi Kobi, thanks for your feedback!

The main point there is to emphasize that unit tests verifies the unit’s behavior in isolation from the environment and other units. As for the difference between test types, I think it’s more a terminology question. Integration test spectrum may vary from testing interactions between two classes to testing the whole subsystem in the real-life (or close to it) environment.

From my point of view, the main difference between system and integration test is that system test always treats the whole system as a black box.

Petr Mlčoch
Perfect article. Clean, understandable examples and solutions for fix. Passed to others developers.
Sergey Kolodiy
Thank you Petr! 🙂
Ollie Ford
Interesting read, thanks! I came here via [a discussion this article sparked on Programmers.SE](http://programmers.stackexchange.com/questions/288405/is-testable-code-better-code) which may interest you/others if you haven’t seen it.
Sergey Kolodiy
Hi Ollie, thanks for the link! Looks like I am a little bit late to the party, the question has already been closed. Interesting thoughts and comments, but I’m not quite agree with the accepted answer.

First of all, I believe that there is a strong correlation between code maintainability and testability (this is one of the points I tried to demonstrate in the article). Of course, you should always be pragmatic and not reduce that techniques to an absurdity — for example, it doesn’t make much sense to create an interface for the "+" operator in order to be able to mock it.

Accepted answer, essentially, is proposing using automated integration tests or "better test framework" that can replace static or concrete methods instead. As shown in the article, integration tests have different purpose and using them to verify subtle edge cases in the code is an overkill. About "better test frameworks": it is possible to use mocking frameworks like Microsoft Fakes [1] that support shims. As pointed there, <cite>a shim modifies the compiled code of your application at run time so that instead of making a specified method call, it runs the shim code that your test provides.</cite>

However, I highly discourage shim-based unit testing because it gives you an illusion that your code is OK when it’s actually not. It is still tightly coupled to the concrete impure factor (like writing to the DB or reading system time), so, consequently, such APIs lie about their dependencies and are hard to reuse and maintain. I prefer to always use stub-based unit testing and decouple things using interfaces or other techniques. Some .NET classes like <code class="C#">HttpClient</code> does not have corresponding interfaces, so you can wrap them into a class that implements an interface.

Anyway, I’m glad this article inspired such an interesting discussion on Programmers.SE!

[1] https://msdn.microsoft.com/en-us/library/hh549175.aspx

Ollie Ford
It seems to be open now – and note that the "accepted" answer is chosen solely by the question-asker, so there can certainly be an element of "thanks, you said what I wanted to hear"!

I’m not nearly experienced enough to really have much of an opinion myself (still working on being more test-driven, never-mind making the code more testable!) – I just found the discussion and your original article interesting 🙂

Flavio Escobar
Great article! Really useful!
But why are you so sure about "Using Singletons is a bad practice"?
Sergey Kolodiy
Hi Flavio, I’m glad you like the article! Well, Singleton anti-pattern is discussed in the article, here is the short summary:

1. Tight coupling: Singleton can’t be replaced with other implementation (either fake or real-life).
2. Singletons hide the real dependencies, making your APIs obscure.
3. Singletons violate the SRP principle.
4. Singletons are a potential sources of side-effecting or non-deterministic behavior. In most cases, such stuff should be encapsulated and invoked using an interface, not the concrete implementation.

Luuk Krijnen
Hi Sergey, Great article.

While reading in my search on how to test my own software there are some specific questions.

I wrote a generic repository base class with caching. The cache results are stored in a Generic List of T wrapped in a type with the object lifetime. These cache items are stored in a private static readonly list that is instantiated in the baseclass constructor. The derived types implement the connection specific logic (CRUD) where the baseclass keeps track of the cached items (difficulty is with locking when using multithreading). These repositories should by instantiated using a IOC Container implementing the singleton pattern (I want only a single cache repository per type for the whole application). I tried using moq for unit testing but I’m having problems implementing the tests. Reading your article I think I stepped in many pitfalls knowing that it seams difficult to write a unit/integration test. Can you help me out. Problem is posted: http://stackoverflow.com/questions/33231813/verify-if-an-abstract-method-is-called-using-moq/ Where probably Moq is the least of my concerns?!

Shaiju Janardhanan
Good article with lots of insights
Umair Jameel
Have a look at this amazing series of unit tests best practices with practical examples.


Janbask – Online IT Training
Really Informative. This articles covers almost everything with great examples
Sergey Kolodiy
Hey Janbask, thank you for the feedback! Just wondering, which content would you also want to be covered in this article? If there is a room for improvement, we can do it!
Alexis Duran
Excellent article!
Umair Jameel
Check out the best best unit testing practices…
Zain Fathoni
Hi @sergey_kolodiy:disqus,

I am quite new in Unit Testing, thus I still have some confusion in implementing it.

I am trying to refactor some static methods to make them testable.
But since Interface in C# doesn’t allow static modifier, how am I suppose to refactor those methods so I can produce "fake" versions of them?

I considered changing those methods into non-static ones, but that would make the methods less suitable semantically, because they are supposed to be attached to the Class, instead of the Object.


That was cool. Lucky the company which employs you. This nice blog piece wraps up my trip to Russia after a week in St Petersburg and 3 days for the May 9th parade in Moscow I now have to head back West again. Thanks !
I’m guessing your calling this all over your app to get the config settings. Here how I have solved this in the past

Remove all the statics. Generate an interface for you Config Utils class. Make the constructor private and create a very simple factory that returns an interface rather than the concrete class. Like so…

public interface IConfig
string ConnectionStringget;

public class Config : IConfig
public string ConnectionString{get return ConfigurationManager.Settings["ConnectionString"];
private Config(){}

public static IConfig GetConfig()
return new ConfigSetting()


Now pass in the config settings where needed (instead of using statics). Example:

public string DoSomething(IConfig config)

///doing stuff with config.ConnectionString

This gives you IoC, allows you to easily mock your config and helps mitigate co-workers from passing around con-concrete classes by use of the private constructor. Give the method the toolbox… don’t let it provide its own.

Can anyone recommend some good books for improving testability of code?
Pavel Přibyl
Thanks Sergey, very good article. This exactly sums up my thoughts that I am trying to pass to my team, but I was not able to express them so clearly. Love the pictures as well, btw 🙂
Majid Rafigh
Nice job Sergey, it was really comprehensive and straight forward.
Nicholas Vella
Very nice article! Well done!
Excellent article! Thank you for giving a clear and understandable examples, they helped me a lot. I really appreciated that you also covered not just the unit testing, but other topics, such as IoC and Dependency Injection. Thanks again!
Great article!
Great article, however one crucial (maybe obvious) thing is missing :

To build unit-testable systems, don’t build business-logic in background-systems, such as procedures in database

Andrew C
For unit testing you shouldn’t need to get the data from the web, otherwise you’re writing integration tests. You should have some object that kicks off the async task, another object that IS the async task, and yet another object that uses the data from the async task. All of these should be unit tested independently of each other. You should utilize dependency injection and mock the injected dependencies, so that there’s never any need to run an asynchronous task in any of the unit tests.
Thank you for your reply, Andrew! Indeed I have been thinking about this topic since I read the article. With your explanation, I can see more clearly how should I apply it for my particular case.
Juan Quinteros
This article is really amazing.

It has changed the way I write code. I read about unit testing before but I had never found (until now) an article with so good examples and so good explanation on theory about unit testing. Thank you very much, Sergey!

Greetings from Argentina.

Just found this useful article. Thanks.
JanBask Training
Covers some genuine points and which are important from SDLC point of view as well
Wissam Aboueida
Very nice article. It cleared out alot of assumptions I had in my mind. Thanks Sergey
wonderfully explained with simple code examples..
JanBask Training
Informative and interesting article about unit testing. You described every thing in detail. Thanks for sharing with us.
Keep it up!!
Koray Tugay
Good article.. Thank you.
Edison Saul Castillo
Loved the Article, thank you!
Frči Smrči
One of the rare articles that you just can’t stop reading, just like a good book. Thanks!
Zenthei Aranda
great article , i have seen another articles and they only talk but without code i don’t understand it very well like yours
Kaushal Kishore
Awesome article! This was exactly what I was looking for. Your efforts can be clearly seen through this great article.
Sandeepkumar Parekh
Clean , easy to understand and well explained article Sergey. Keep up the good work.
Fuck this site and it’s "exit intent" garbage.
Lloyd Atkinson
Great article, bookmarked.
Tan Jing Tao
Excellent article, love the bad vs good testable code examples, and the detailed explanations behind the code. Thanks!
Lars Kniep
Thanks for this well written article!
Chris H
Wow, that was one of the best articles I’ve read in a long time. Thanks!
Top-notch article, great to not only show issues with untestable code, but how to solve them!
Corry Moss
Great piece, Sergey. Thorough and informative.
Zeeshan Fawad
Really great article by Sergey, Thanks.

I need one clarification that I am using if condition in my unit test as mention in below code

When I test code coverage, this if statement is not covered in my coverage. Can any once tell why it is not covered in my coverage?

Maximiliano “TetasDaJojo” Pare
Excellent article Sergey!
Leandro Curioso
Nawawish Samerpark
Great article! Thanks 🙂
Phuc Coi
Krishna Kishore Rajagopal

Have written a blog on how to be a successful tester. Hope it helps

jacob maurier
This was really well written. Great job, man!
Karla Flores
This article is amazing…so useful.
Now I have a question. Now I have many unit test. there is a tool to generate a report like a field that contain what tests are passed or failed without using the window test explorer?
Kiran Kumar Chava
Well written!

comments powered by Disqus

Trending articles
Relevant Technologies
  • QA
  • C#
  • Agile
About the author
Sergey Kolodiy
Sergey Kolodiy
.NET Developer
Sergey is a software engineer with extensive development experience in the .NET technology stack, with strong architecture and coding skills. He loves to work on complex and business-critical tasks with full involvement, high productivity, and great enjoyment. He is a big fan of clean, testable, and maintainable code and has worked for a number of successful projects ranging from small startups to complex enterprise applications.
Hire the Author

Home Blog Unit Tests, How to Write Testable Code and Why it Matters