When we talk about unit tests, we think about input values and return values to/from methods. Returned values are checked against expected values as a way to verify behavior of codes. But how would you test codes that do not return any values? Essentially, we resort to stubbing out void methods. That is easy in Mockito!
[wp_ad_camp_5]
Software Requirements
- Java 7
- Eclipse Luna
- Mockito 2.0.2-beta
- JUnit 4.12
- Maven
Codes to Test
Below is a sample class with a single void method. The main behavior of the codes processes PersonRecord objects conditionally – if status is “UNDERAGED”, use service.processUnderAged(…) method; otherwise, use service.processLegalAged(…). There are also null-checkings at the start of the void method.
[wp_ad_camp_4]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.turreta.mockito.voidmethod; public class VoidMethodClass { private PersonService service; /** * @return the service */ public PersonService getService() { return service; } /** * @param service * the service to set */ public void setService(PersonService service) { this.service = service; } /** * The main logic or behavior to test using Mockito * * @param record */ public void process(PersonRecord record) { if (record.getId() == null || record.getStatus() == null) { return; } if (record.getStatus().equalsIgnoreCase("UNDERAGED")) { service.processUnderAged(record); } else { service.processLegalAged(record); } } } |
The Unit Tests
PersonRecord with null id
If id is null, the method returns immediately and no codes executed except PersonRecord.getdId(). We did not even use the service code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Test public void testProcess_record_with_null_id() { Mockito.when(record.getId()).thenReturn(null); voidMethodClass.process(record); // We check if getId() was invoked. Mockito.verify(record, Mockito.times(1)).getId(); // We check if only getId() was invoked, and not getStatus() Mockito.verify(record, Mockito.only()).getId(); // No methods invoked in service object Mockito.verifyZeroInteractions(service); } |
PersonRecord with “1000” id and null status
Now PersonRecord.id is not null but status is. The codes still invoked getId() but returns false. The getStatus is invoked because of the OR condition in the if statement. Each of these methods were called once. The service codes remained unused.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Test public void testProcess_record_with_null_status() { Mockito.when(record.getId()).thenReturn("1000"); Mockito.when(record.getStatus()).thenReturn(null); voidMethodClass.process(record); // We check if getStatus was invoked inOrder.verify(record, Mockito.times(1)).getId(); inOrder.verify(record, Mockito.times(1)).getStatus(); // No methods invoked in service object Mockito.verifyZeroInteractions(service); } |
PersonRecord with “1000” id, and “LEGALAGED” status
Both getId() and getStatus() were used. getStatus() was used for the second time to compare its value against “UNDERAGED”. Only processLegalAged(…) was invoked on the service object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Test public void testProcess_record_record_legal_aged() { Mockito.when(record.getId()).thenReturn("1000"); Mockito.when(record.getStatus()).thenReturn("LEGALAGED"); voidMethodClass.process(record); // We check if getStatus was invoked inOrder.verify(record, Mockito.times(1)).getId(); inOrder.verify(record, Mockito.times(2)).getStatus(); Mockito.verify(service, Mockito.only()).processLegalAged(Matchers.any(PersonRecord.class)); } |
PersonRecord with “1000” id, and “UNDERAGED” status
Both getId() and getStatus() were used. getStatus() was used for the second time to compare its value against “UNDERAGED”. Only processUnderAged(…) was invoked on the service object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Test public void testProcess_record_record_under_aged() { Mockito.when(record.getId()).thenReturn("1000"); Mockito.when(record.getStatus()).thenReturn("UNDERAGED"); voidMethodClass.process(record); // We check if getStatus was invoked inOrder.verify(record, Mockito.times(1)).getId(); inOrder.verify(record, Mockito.times(2)).getStatus(); Mockito.verify(service, Mockito.only()).processUnderAged(Matchers.any(PersonRecord.class)); } |
PersonRecord with “1000” id and other status
Status that is neither “UNDERAGED” or “LEGALAGED”, use processLegalAged(…)
[wp_ad_camp_3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Test public void testProcess_record_record_not_undefined_status() { Mockito.when(record.getId()).thenReturn("1000"); Mockito.when(record.getStatus()).thenReturn("UNDEFINED STATUS"); voidMethodClass.process(record); // We check if getStatus was invoked inOrder.verify(record, Mockito.times(1)).getId(); inOrder.verify(record, Mockito.times(2)).getStatus(); Mockito.verify(service, Mockito.only()).processLegalAged(Matchers.any(PersonRecord.class)); } |
Download the Codes
https://github.com/Turreta/VoidMethodsAndMockito