4
votes

How do initialize private fields in JUnit so that when I test a method, the value of the private field will be used. As you can see, the private String searchDate is used in the GetSkillListServiceCustomize, but the searchDate is not initialize yet so the testing fails. I tried using reflection but it throws a NoSuchFieldException:. GetSkillListServiceCustomizeTest.class is my JUnit class while the other is the class I'm testing.

GetSkillListServiceCustomizeTest.class

try {
            Field reader = GetSkillListServiceCustomize .class.getDeclaredField("searchDate ");
            reader.setAccessible(true);
            StringReader stringReader = new StringReader("2017-01-28");
            BufferedReader readerToSet = new BufferedReader(stringReader);
            reader.set(testClass, readerToSet);
            returnVal = testClass.processOutput(mapVar);
        } catch (NoSuchFieldException e1) {
            e1.printStackTrace();
        } catch (SecurityException e1) {
            e1.printStackTrace();
        }

        assertTrue(returnVal != null);
   }

GetSkillListServiceCustomize.class

public class GetSkillListServiceCustomize 
    extends GetSkillListService 
    implements ServiceIF<GetSkillListInputDTO, GetSkillSummaryDisplayDTO> {

    private String searchSite;
    private String searchDate;

    ...more codes

    protected GetSkillListOutputDTO processOutput(Map<String, Object> resultMap) 
            throws ServiceDBException, ServiceAppException {

    ...//more codes
     List<GetSkillListOutputDTOList> getskilllistoutputdtolistTmpWrap = null;
    if (employeeMasterList != null && !employeeMasterList.isEmpty()) {
        getskilllistoutputdtolistTmpWrap = new ArrayList<>();
    }
    if (employeeMasterList != null && !employeeMasterList.isEmpty()) {
        List<EMPLOYEE_MASTER> empMasterlistNoDeleted = employeeMasterList.stream()
                .filter(e -> { 
                    try {
                        return (e.getDel_Datetime() == null 
                                    || (sdf.parse(e.getDel_Datetime())
                                            .compareTo(sdf.parse(this.searchDate)) > 0));
                    } catch (ParseException ex) {
                        ex.printStackTrace();
                        return false;
                    }
                })
                .collect(Collectors.toList());

      ...//more codes in the bottom
3
Try taking the trailing space off the field name. - Nathan Hughes
Why you don't initialize it in the constructor? and why you need to test variable you didn't even initialize? - Fady Saad
because the initialization of the searchDate field is done in another method, which will be passed in the method written above. That's why, I'm looking for a way that will set a dummy value to the searchDate field which will be used when the '.compareTo' is executed. - KaelJasper
The main problem is your object to be tested is not properly constructed. An object should be fully initialized before it can be tested. Using reflection to initialize fields of the object is not good practice unless the code you're trying to test is legacy code. - ujulu

3 Answers

4
votes

JUnit provides marker for init method @Before. In init method you can initialize almost everything you want. To have useful access to private fields I would recommend to use third party utils, for example

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.10.RELEASE</version>
    <scope>test</scope>
</dependency>

in your test you would be able use setter for private field like this:

@Before
public void setUp() {
    org.springframework.test.util
       .ReflectionTestUtils.setField(
           theGetSkillListServiceCustomizeInstance,
           "searchSite",
           "valueToSet");
}
1
votes

I would suggest to create a setter for this field and made a comment that this setter is only for unit testing.

-3
votes

I suggest initializing private fields in the constructor of the class.