0

I have a function that checks to see if a file exists or not. If it does exist, it proceeds to execute some code. It's this code that I need to test.

I cannot have an actual file in the test suite, so Im attempting to mock Files.exists() to have it return true.

The function looks similar to this

protected function foo() {

    Path jsonPath = getPath();

    if (Files.exists(jsonPath)) {
        // Code to test...
    }
}
  • At least one option, if you can add it without much trouble, is to use a "testing" file system (such as https://github.com/google/jimfs) to avoid needing to interact with the real file system. You shouldn't need to change too much of your code, simply have `getPath()` return a `Path` implementation from the "test" file system implementation. – Slaw Sep 02 '21 at 20:06
  • Does this answer your question? [Mocking static methods with Mockito](https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito) – talex Sep 02 '21 at 20:15
  • @talex I found this thread before and did try most of the applicable mock implementations but it still doesnt work sadly. `getPath()` is a bit of an oversimplification, as the original function call has some path resolution code that will not work with a testing file system. – Aquib Zulfikar Sep 03 '21 at 05:24
  • You can move call to "Files.exists(jsonPath)" into a helper method (either in the same class or in some helper class), then you do not have to intercept call to static method, but can use normal mockito-stuff. – Seb Sep 03 '21 at 07:14
  • @AquibZulfikar show us what you end up with and explain what problem do you have. It is hard to help if we don't know what problem you facing. – talex Sep 03 '21 at 08:40
  • Just curious, but why can't the path resolution work with a test file system? One of the nice things about NIO2 is the fact that you only interact with a well-defined interface and for the most part don't care about the implementation. For instance, the implementation on Windows is different than the implementation on MacOS. But your code doesn't care. Dropping in an in-memory file system like JIMFS should be possible—so long as your code doesn't have any hard-coded dependencies on the default file system. – Slaw Sep 07 '21 at 04:42
  • @Slaw After fiddling around with the code a bit I ended up making use of a file system as you suggested. Turns out it was pretty much the only way I could get to test the code without resorting to mocking anything. At the end of the day, it seems mocking wasnt the answer after all. Thank you for your suggestion – Aquib Zulfikar Sep 08 '21 at 05:05
  • I'm glad you got it to work. The only other option I could think of, that seems feasible to me at least, is to add a layer off abstraction "above" the file accessing code. You could then mock that abstraction during testing while using the real code only during production. Like Seb suggested. But I still like the file system approach, as it _should_ require less modification of your code. – Slaw Sep 08 '21 at 05:25

2 Answers2

1

As suggested in the comments of the thread, testing the functionality using a testing file system was a better approach than attempting to mock the exists() function without resorting to some major changes to the class structure.

1

If context of your function is class, just create wrapper for Files.exists and mock it in tests. That way you will be able to check your functionality, unfortunately at the same time the only way to test newly created class is thru integration tests without mockito.

class CheckIsFileExist{

   operator fun invoke(jsonPath: String) = Files.exists(jsonPath)
}