This is a ``Test Double'' exercise. Work in groups. We'll do the exercise one step at a time, with discussion between steps. If you haven't seen this before, it's a bit counterintuitive.
Consider testing a class that implements a service for making reservations.
We don't really care what the reservations are for: dinner, lodging, transport, whatever.
Let's call this class ReservationService
and suppose it has a dependency component, namely
a ranking service that scores customers,
with the idea that higher ranking customers get better arrangements.
Note that we are not testing
the ranking service.
Indeed, the ranking service might be from a third party,
it might be expensive (in time or money),
or it might be stochastic, with rankings varying over time.
Since these are all awkward for testing, we'd like to replace the ranking
service with a fake for the duration of our tests.
One standard implementation (with unfortunate consequences for testing)
uses a static factory to set the ranking service inside the
reserve()
method.
public class ReservationService { // instance variables, constructors, other methods omitted for now public void reserve( Customer customer) { RankingService rankingService = RankingServices.getRankingService(); // more code that uses the ranking service by calling // public Rank getRank(Customer customer) // on the rankingService object. } }Great. Let's see what a test case looks like:
@Test public void testReservationService() { ReservationService reservationService = new ReservationService(); Customer customer = ... // do I really want to call reservationService.reserve(customer) ??? RankingService fakeRankingService = new FakeRankingService(); // are there other ways to create a fake ranking service? // can I make the reservation service use my fake ranking service? }
Suppose we pull the rankingService
variable out as an
instance variable in the ReservationService
class.
This a step in the right direction.
Why? (Your answer should say something about "seams").
What does the reservation service code look like now?
What does the test code look like now?
What else do we need to do in the ReservationService
class?
Hint: think about "enabling points".
How does this help in the test code? Hint: think about "exploiting enabling points".
Finally, I need some assertions. What can I say about the fake ranking service that I can't say about the real ranking service? Vice versa? Hint: think about "state testing" vs. "interaction testing". Hint: Recall that you have total control over the fake ranking service.
How does this exercise square with standard development advice?