I am trying to learn JUnit. Working on a particular problem I decided to use JUnitParams parameter providers. Each set of parameters for a test method I'm writing should contain two input values and a list against which results of a method call would be tested:
private static final Object[] getConstraints() {
return new Object[]{
new Object[]{15, Equipment.WHITEBOARD, Arrays.asList(new Classroom[]{classroomA, classroomB})},
new Object[]{15, Equipment.PROJECTOR, Arrays.asList(new Classroom[]{classroomB})},
new Object[]{15, Equipment.MICROPHONE, Arrays.asList(new Classroom[]{classroomA})},
new Object[]{30, Equipment.WHITEBOARD, Arrays.asList(new Classroom[]{classroomB})},
new Object[]{30, Equipment.PROJECTOR, Arrays.asList(new Classroom[]{classroomB})},
new Object[]{30, Equipment.MICROPHONE, Arrays.asList(new Classroom[]{})},
new Object[]{45, Equipment.WHITEBOARD, Arrays.asList(new Classroom[]{})},
new Object[]{45, Equipment.PROJECTOR, Arrays.asList(new Classroom[]{})},
new Object[]{45, Equipment.MICROPHONE, Arrays.asList(new Classroom[]{})},
};
}
classroomA
and classroomB
are actually Mockito stubs prepared before each test execution:
@Before
public void setUp() {
classroomA = mock(Classroom.class);
classroomB = mock(Classroom.class);
classrooms = Arrays.asList(new Classroom[]{classroomA, classroomB});
when(classroomA.getName()).thenReturn("A");
when(classroomA.getCapacity()).thenReturn(20);
when(classroomA.getEquipment()).thenReturn(Arrays.asList(new Equipment[]{Equipment.WHITEBOARD, Equipment.MICROPHONE}));
when(classroomB.getName()).thenReturn("B");
when(classroomB.getCapacity()).thenReturn(40);
when(classroomB.getEquipment()).thenReturn(Arrays.asList(new Equipment[]{Equipment.WHITEBOARD, Equipment.PROJECTOR}));
bookingSystem = new BookingSystem(classrooms);
}
The problem occurs when I try to use aforementioned lists of Classroom
objects:
@Test
@Parameters(method = "getConstraints")
public void shouldBookClassroomMeetingConstraints(int capacity, Equipment equipment, List<Classroom>
suitableClassrooms) {
Assert.assertTrue("Should book a classroom that has a minimum capacity of " + capacity + " and has " +
equipment,
suitableClassrooms.contains(bookingSystem.book(capacity, equipment, ANY_DAY_OF_WEEK, ANY_HOUR)));
}
Debugging shows that during the first run suitableClassrooms
contains 2 objects, but further inspection shows that all elements are null - the stubs I prepared are not there. Obviously, the tests don't pass or fail where they should pass or fail.
Is there a limitation on using JUnitParams with Mockito or am I using them wrong? What is the right way to use them?
It is also possible that this is a wrong technique of unit testing. If this is the case, what is the proper way of writing a test that verifies if the result of a method call is in a given array?
You test doesn't work because JUnitParamsRunner
runner collects parameters for test (i.e. invokes getConstraints
method) before invocation of @Before
methods and even before @BeforeClass
. So classroomA
and classroomB
are null at that moment. That is why suitableClassrooms
consists of null elements.
The solution is to initialize classroomA
and classroomB
in the getConstraints()
method.
Also I believe you can get rid of mockito here. Classroom
looks like POJO and it's not necessary to mock POJOs. In such case you just need to create Classroom
instance and fill it with necessary data.