Issue
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
Solution
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.
Answered By - Fred