Test-Driven Development - How to write a test before none of implementation code exists

Create EnrollingServiceTest class in src/test/java in the same package as EnrollingService

class EnrollingServiceTest {
    private EnrollingService enrollingService;

    @Before 
    public void init() {
           enrollingService = new EnrollingService();
    }

    @Test
    public void testEnroll() {
           boolean result = enrollingService.enroll(1l, 1l);
           assertTrue(result);
    ...

IDE (I am assuming you are using IDE) shows errors - EnrollingService does not exists .

Point cursor on EnrollService - IDE will offer to create a class - let it create in src/main/java

Now IDE says that enroll(long, long) method is missing - let IDE create it for you.

Now IDE shows no errors. Run the test - it fails. Go to enroll and start implementing the logic

And so on...


This will become clearer when you focus on the expected behavior of the code rather than the implementation of the code. So given the scenario you outlined you may arrive at the conclusion that you will have to write the enroll() method in some class. You can then consider how you are going to test this class.

You begin by considering the conditions of the class and what is expected of it. Maybe you can identify certain invariants of the class. In that case to test the class you consider the ways in which that invariant can be violated.

So taking the statement: a student may register for a maximum of 3 courses per semester, you consider the ways that this can occur.

  1. Student is registered for 0 courses for the given semester, attempt to register for a course, result: registration successful; student is now registered for 1 course for the given semester.
  2. Student is registered for 1 course for given semester, attempt to register for a course, result: registration successful; student is now registered for 2 courses for the given semester.
  3. Student is registered for 3 courses for the given semester, attempt to register for a course, result: Fail (maybe exception is thrown?)
  4. etc etc

Next you actually write these tests. Each of these can be a test method. So the test method would ensure that the objects are created and the environment is set up as expected. Then call the method and compare the result to the expected result. If what you expect to happen actually does happen then the test passed.

Now, initially, since you did not as yet write the method the tests would not actually pass. But as you start to write code your tests would start to pass and eventually 100% of your tests will pass at which point you are satisfied that your code meets the requirements.


public void shouldNotEnrollInMoreThanFourClassesInASemester() {
  Enroller enroller = new Enroller();
  Student student = new Student();
  Semester one = new Semester();
  Semester two = new Semester();
  Course geology = new Course(one);
  Course architecture = new Course(one);
  Course calculus = new Course(one);
  Course sociology = new Course(one);
  Course geometry = new Course(two);

  assertOk(enroller.enroll(student, geology));
  assertOk(enroller.enroll(student, architecture));
  assertOk(enroller.enroll(student, calculus));
  assertNotOk(enroller.enroll(student, sociology));
  assertOk(enroller.enroll(student, geometry));
}