Issue
In my code I try to test a file from which the path is given as string to a method like so:
TestClass testClass = spy(new TestClass());
@Test
public void test() {
testClass.someMethod();
doNothing().when(testClass).someOtherMethod(any(String.class));
Mockito.verify(testClass, times(1)).someOtherMethod(argThat(this::checkFile));
}
private boolean checkFile(final String filePath) {
boolean fileLegit = true;
File file = new File(filePath);
assertThat(file).exists();
try {
// Some testing on the file
} catch (IOException | IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
fileLegit = false;
}
file.delete(); // <- Trying to delete
return fileLegit;
}
Here I get the following exception:
java.lang.AssertionError:
Expecting file:
<path\to\file>
to exist
When I remove the file.delete()
everything works fine, but the file does not get deleted (obviously). I need to delete it after testing though, so do you have any clue why this happens and how to fix it?
Here would be the TestClass object, because some people are intrested in it (blindcoded, but you get the idea):
public class TestClass {
public void someMethod() {
List<String> content = new ArrayList<>();
content.add("test");
Path path = Paths.get(/* Choose a path */);
if (!Files.exists(path)) {
Files.createFile(path);
}
Files.write(path, content, StandardCharsets.UTF_8);
someOtherMethod(path.toString());
}
void someOtherMethod(String filepath) {
System.out.println(filepath);
}
}
Solution
I assume that testClass
is a spy
on your TestClass
object, even so your example does not mention this. Note that you should try to restrict your usage of spies
to legacy code if you can.
Your problem is related to the fact that the checkFile
method is invoked twice when you run your unit test. You wrote this code based on the assumption that your method is only invoked once, however that is not how Mockito
works in this case.
You can easily verify that by adding a breakpoint
or a System.out
to your method.
To fix this separate the file deletion logic from the matcher. You might want to add a cleanup (@AfterEach
) method instead.
Answered By - second
Answer Checked By - Clifford M. (JavaFixing Volunteer)