SWE 437 In Class Exercise # 9
Test Doubles

Names:

Instructions: Work with your neighbors in groups.

This is a ``Test Double'' exercise. We'll do the exercise one step at a time, with discussion between steps.

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?