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.