Adding A Parameter To A Method With TDD
It’s been a while since we’ve had an article in the series on Test-Driven Development (TDD). Last time we added an Add() method to a ShoppingCart class. When we’re done with Add(), it will allow us to append a quantity of a Product into an instance of a ShoppingCart. We have a bit of work ahead of ourselves – right now Add() takes no parameters and is an empty method:
Today we’ll start fleshing this method out. Over the next several weeks we’ll keep chipping away at Add() using TDD.
OK, let’s get into it.
For Add() to do some useful work it will need to take in some data – it will need parameters.
What kind of parameters shall Add() take? Hmm, I guess it will take in a product as well as a quantity. E.g. 3 Apples, 1 Ferrari, 8 Bananas, etc.
We want to extend our empty, parameterless Add() bit by bit using TDD. Therefore, let’s write a test that forces Add() to, say, require a Product parameter.
TDD is all about writing the most straightforward possible test each time. In our case, what is that simplest possible unit test we can write to force Add() to take a Product parameter?
Answer: How about a null Product? It is potentially possible for Add() to receive a null value for the Product parameter. Since a null Product is not a valid scenario, Add() should probably throw an exception. Specifically a MissingProduct exception.
Here is our unit test:
We are following the principle of The Thorns and The Gold. To recap, this is the idea that before we write tests that handle valid scenarios, we first explore invalid inputs. Hence the null Product test before a test for a ‘Porsche’ Product.
OK, our test contains two build errors:
- Add() does not have a parameter, and
- The MissingProduct exception is unknown.
Let’s fix these problems.
Firstly, let’s add Product as a parameter to ShoppingCart.Add():
Product is a required new type. The simplest thing to do on our part is to create Product as an empty class:
The build error in Add() has disappeared:
Unfortunately, the original unit test that we used to drive the creation of the Add() method in the first place does not expect a parameter.
This test existed for the sole purpose of generating Add(). It is now obsolete. We’ll delete it.
OK, what does our Product parameter unit test look like now?
OK, that is much better – only one build error remaining.
Let fix this error by creating the MissingProduct exception:
Our unit test is building.
Let’s run all the tests and see what happens:
Right. The test is complaining that even though we expected Add() to throw a MissingProduct exception, this did not happen. How do we fix this? Let’s look to the last rule of The 3 Rules Of TDD for guidance:
Rule 3: You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
OK, we should write the least code possible in Add() to throw the MissingProduct exception. I think this might do the trick:
But we didn’t check for a null Product! That is true. We will write the null Product check as we add more unit test next time.
For now, let’s run all the unit tests again. Viola! All tests pass.
Today we used TDD to force a method to accept a parameter. Next time we’ll add a parameter for quantity to our ShoppingCart.Add() method too.