0

Lets say a university offers courses and courses are attended by students:

class University{
    List<Course> courses;
}

class Course{
    Category category;
    List<Student> students;
}


class Student{
    Gender getGender();
    boolean hasGender(Gender gender);
}

I also have a class Filter which should return all male students which attend courses in Category.MATH

public class Filter{


  University university;
   
  List<Student> selectSubgroup(){
     //to be implemented
  }
}

I normally use the builder pattern to write tests in such cases and i like it because of the readability.

class FilterTest{
    @Test
    void testThatOnlyMaleStudentsInCategoryMathAreSelected(){
        when(university.getCourses()).thenReturn(
            aCourse()
                .with(Category.MATH)
                .with(
                    aStudent()
                        .withGender(Gender.MALE),
                    aStudent()
                        .withGender(Gender.FEMALE)
                )
        );
        
        assertThat(filter.selectSubgroup()).hasSize(1);
    }
}

However, using this approach implies using the real method hasGender of class Student, so the test is not isolated. Using mockito, a test might look like this:

class FilterTest{
    @Test
    void testThatOnlyMaleStudentsInCategoryMathAreSelected(){
    
        when(university.getCourses()).thenReturn(Arrays.asList(course));
        when(course.getStudents()).thenReturn(Arrays.asList(student, student2));
        when(course.getCategory()).thenReturn(Category.MATH);
        when(student.hasGender(eq(Gender.MALE))).thenReturn(true);
        when(student.hasGender(eq(Gender.FEMALE))).thenReturn(false);
        when(student2.hasGender(eq(Gender.FEMALE))).thenReturn(true);
        when(student2.hasGender(eq(Gender.MALE))).thenReturn(false);
        
        assertThat(filter.selectSubgroup()).hasSize(1);
    }
}

I find this less readable, but all the dependendent classes are mocked. So, which approach is better?

peer
  • 257
  • 2
  • 11
  • 1
    In your case, definitely go with your preferred approach (without mocks). You may be in favor or agains mockist approaches (Software Engineering at Google has a good discussion of pros and cons: https://abseil.io/resources/swe-book/html/ch13.html) but mocking POJOs is a no-go even if you embrace a mockist approach. – Lesiak Sep 02 '22 at 19:28
  • @Lesiak Is `Student` a POJO if it has the method `hasGender`, in which there might be some complicated business logic? I mean, if i use the approach without mocks, the test relies on the implementation of `hasGender`, so the test is not isolated. – peer Sep 12 '22 at 08:39

0 Answers0