One of the problems I had when I started to learn unit testing, and a concept that seems to be hard to grasp as I teach others about unit testing, is this concept of testing just a unit. What is a unit after all?
What is a “Unit”?
Simply, a unit is one feature or functionality that your application needs to perform. The problem I see most people have is not that they don’t know how to test a unit so much as they don’t understand what “a feature” or “a function”.
This is best illustrated by a recent testing problem.
The feature that was being introduced was a classic role based security issue with a twist. A user could be one of three different roles. But the record they are trying to view could also be part of three separate roles. You can look at a record based on the intersection of the two.
How would we test this? More accurately, how would you design this so that you could test this?
If you think of the problem as “can we log in?”, you will attempt to test this as one unit. But you actually have at least three units to this problem.
- What role is the logged in user
- What role is the record you are trying to view
- Given a particular user role and a particular record role, can the user view the record.
Why is testing “Units” difficult to understand?
But now that we’ve broken out the problem, we will probably still run into trouble when we start to creat test for this because, if you are like most of the programmers I know, you’ll make at least one of these methods call down to your data access layer in order to figure out what role who is in.
Now, I understand why you might do this. Most of our code looks something like this:
View –> Business Rules –> Data
That is, the view calls down to the business rules which calls down to the data.
The problem with this way of thinking about your code is that you will always have dependencies on other code futher down the chain making the code nearly impossible to ‘unit’ test.
What you will need to do, instead, is to think about how you will test this code as you are coding. You’ve heard me say it before, but this is one of the benefits of unit testing. It makes you think about the design from two different perspectives, which ultimately makes you code more solid and more flexible.
So, one way you might go about separating your code from the data is by using dependency injection. What I’m talking about here is simple injection. No frameworks.
So, let’s say you have a class you may have called user role. Given a user id, it will return a role. How could we code this so that it doesn’t matter where the code comes from?
By declaring an interface to a user role object maybe and then passing an object of that type to the constructor.
By doing this, you can use a fake object when you are testing and a real object when you are using the system in production, but your code won’t really care which one is being used.
At some point we will need to retrieve data. But the data is always just a side effect. If you have a way of getting at the data, and you are confident it works, because that standard mechanism has been tested, then you don’t need to write test for the data access piece, you only need to write test for “given I have good data, this method will do this.”
Why Unit Test Generation Tools Are Dangerous
Other post in TDD
- Why Don't You Practice Test First Development? - February 20th, 2014
- Test Driven Specifications - February 25th, 2014
- Unit Test Structure - March 11th, 2014
- When You Really Need All Of Your NUnit Test In One Class - March 18th, 2014
- TDD Isn’t All About Testing - March 25th, 2014
- Automated Web Application Functional Testing - April 1st, 2014
- What Not To Test - April 9th, 2014
- Make Your Test Work For You - April 18th, 2014
- Don’t Comment Out That Test - April 24th, 2014
- The Proper Function of QA - May 1st, 2014
- TDD Saves Time – A Story - May 22nd, 2014
- It is called "Unit Testing" for a reason - August 28th, 2014
- Is Your Architecture Crippling Your Unit Testing? - September 4th, 2014
- Selenium Performance Improvements - October 2nd, 2014
- Technical Debt Is Inevitable - October 16th, 2014
- NUnit, Unity Dependency Injection, MOQ and Private Fields - October 23rd, 2014
- NUnit & Visual Studio - December 4th, 2014
- Software Architecture without Test Driven Development is DANGEROUS! - January 29th, 2015
- NUnit Test Code Structure - February 5th, 2015
- Excuses For Not Testing - February 26th, 2015
- Why Johnny Can't do Test Driven Development - March 5th, 2015
- Changing Habits - March 19th, 2015
- 100% Code Coverage Possible? - March 26th, 2015
- TDD Gamification - Turning Test Driven Development into a Game - April 23rd, 2015
- Run NUnit from Visual Studio - April 30th, 2015
- The Parable of The Road Line Painter - May 28th, 2015
- The Fallacy of Motion - July 23rd, 2015
- Test Driven Learning - An Experiment - March 24th, 2016
- 3 Reasons You Believe 100% Code Coverage Is Impossible - May 26th, 2016