Skip to content
Advertisement

Condition fails in Junit5 & Mockito

I am trying to write the test case for my application and I cannot get past a condition even after providing what is expected, from what I know.

Here is my test class.

@ExtendWith(MockitoExtension.class)
class AppConfigTest {

  @Mock
  @TempDir
  File mockedFile;

  @InjectMocks
  private AppConfig appConfig;

  @Test
  void getData() throws Exception {
    File f = new File("f");
    File[] files = {f};

    lenient().when(mockedFile.listFiles()).thenReturn(files);
    lenient().when(mockedFile.isFile()).thenReturn(true);
    assertNotNull(appConfig.getData());
  }
}

My implementation. The test doesn’t go past the if condition. The test does not cover the code after the condition as it turns true all the time. I need my test to cover keyMap() in the last line.

  private Map<String, String> getData() {
    File[] files = new File(APP_CONST.DIRECTORY).listFiles();
    if (null == files) { // not turning FALSE even after providing mocked "files" array 
      return Collections.emptyMap();
    }
    List<String> keysList = getKeyList(files);
    return keyMap(APP_CONST.DIRECTORY, keysList);
  }

Can anyone please tell me how to correct this please? Using SpringBoot/JUnit 5

Advertisement

Answer

We discussed this in the comments, but in any case, I guess an example is better.

One way you could go about this is to make sure the same folder exists. In the test setup you could simply create it.

@Before
public void setUp() {
   new File(APP_CONST.DIRECTORY).mkdirs();
}

Now when accessing it in the implementation there will be a directory. You can also inside the test add files to the directory, so it’s not empty.

Although this works, it has some issues with setting it up and cleaning it up. A better way is to abstract this from the implementation itself and use some kind of provider for it.

A suggestion would be to create an interface where the real implementation returns the real folder and in tests you can mock this.

public interface DirectoryProvider {
   public File someDirectory();
}

public class RealDirectoryProvider implements DirectoryProvider {
   @Override
   public File someDirectory() {
     return new File(APP_CONST.DIRECTORY);
   }
}

you can now make the getData class depend on this abstraction. You didn’t give us the class name, so don’t pay attention to that part:

public class Data {
   private final DirectoryProvider directoryProvider;

   public Data(DirectoryProvider directoryProvider) {
     this.directoryProvider = directoryProvider;
   }

   private Map<String, String> getData() {
     File[] files = directoryProvider.someDirectory().listFiles();
     if (null == files) { 
       return Collections.emptyMap();
     }
     List<String> keysList = getKeyList(files);
     return keyMap(APP_CONST.DIRECTORY, keysList);
   }
}

Now during the test you can just inject your mocked directory/temp dir.

@ExtendWith(MockitoExtension.class)
class AppConfigTest {
  @TempDir
  File mockedFile;

  @Mock
  DirectoryProvider directoryProvider;

  @InjectMocks
  private AppConfig appConfig;

  @Test
  void getData() throws Exception {
    lenient().when(directoryProvider.someDirectory()).thenReturn(mockedFile);

    assertNotNull(appConfig.getData());
  }
}

You can also add files to the temp dir if you need. This however should be enough to pass the if I think.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement