Search code examples
javaunit-testingjmockit

Why should I not be mocking File or Path


I've been struggling with understanding the minefield that is classes supported by the jmockit Mocking API. I found what I thought was a bug with File, but the issue was simply closed saying "Don't mock a File or Path" which no explanation. Can someone on here help me understand why certain classes should not be mocked and how I'm supposed to work around that. I'm trying to contribute to the library with bug reports, but each one I file just leaves me more confused. Pardon my ignorance, but if anyone can point me to the rationale for forbidden mocks etc. I'd greatly appreciate it.


Solution

  • I'm not certain that there's a fool proof list of rules. There's always a certain degree of knowledge and taste in these matters. Dogma is usually not a good idea.

    I voted to close this question because I think a lot of it is opinion.

    But with that said, I'll make an attempt.

    Unit tests should be about testing individual classes, not interactions between classes. Those are called integration tests.

    If your object is calling out to other remote objects, like services, you should mock those to return the data needed for your test. The idea is that services and their clients should also be tested individually in their own unit tests. You need not repeat those when testing a class that depends on them.

    One exception to this rule, in my opinion, are data access objects. There is no sense in testing one of those without connecting to a remote database. Your test needs to prove the proper operation of your code. That requires a database connection in the case of data access objects. These should be written to be transactional: seed the database, perform the test, and reverse the actions of the test. The database should be in the same state when you're done.

    Once your data access objects are certified as working correctly, all clients that use them should mock them. No need to re-test.

    You should not be mocking classes in the JVM.

    You asked for a why about File or Stream in particular - here's one. Take it or ignore it.

    You don't have to test JVM classes because Sun/Oracle have already done that. You know they work. You want your class to use those classes because a failing test will expose the fact that the necessary file isn't available. A mock won't tell me that I've neglected to put a required file in my CLASSPATH. I want to find out during testing, not in production.

    Another reason is that unit tests are also documentation. It's a live demonstration for others to show how to properly use your class.