2

I am trying to understand the JUnit way of imports classes at test time.
I noticed that creating a mock class with the same name of a src class, and the same package, will cause a test to import that one instead of the real src class.
For example :

src/main/java/MyObject.java
src/main/java/ObjectPrinter.java

src/test/java/MyObject.java
src/test/java/ObjectPrinterTest.java

Where both the main/java/MyObject.java and the test/java/MyObject.java declares the same package (both files starts with the same package XXX decleration). The ObjectPrinter.java (which is called by ObjectPrinterTest.java at test time) will have an import XXX.MyObject decleration.

How is it that in test time the import XXX.MyObject will import the test/java/MyObject.java and a 'production' call will call the src/java/MyObject.java?.
Is this kind of directory building safe? Is it common usage?
Where can i read more about this specific flow?

Thanks!

iddqd
  • 1,225
  • 2
  • 16
  • 34

1 Answers1

4

This is a result of how Java dependencies work. When running JUnit tests the src/test/java directory is used as the project to be run, src/main/java is treated as a dependency. When java is trying to resolve an import path it has no idea of knowing if the path is from an internal file or a dependency. Therefore it will first try to resolve it within the project and then look at the dependencies. If it finds a match in the project it will not look any further. In the same way, when running the 'production' code src/main/java is used as the main project with no dependency to src/test/java, therefore it will always get the original implementation of MyObject.

Overwriting classes in this manner is technically safe but not a good practice. It would make it unclear if the original implementation is used.

If you want to keep most of the logic of MyObject but override some of it you should create a stub class in src/test/java, ie. MyObjectStub.

Another way of replacing logic logic for testing is to use a mocking library such as Mockito.

Community
  • 1
  • 1
AleSod
  • 422
  • 3
  • 6
  • Thank you, exactly the answer i was looking for.A small followup question-is the src/test directory the first class lookup even for the project dependencies(i.e,if MyObject was not in the same project/dependency as the test class, but in a parallel project that also have src/MyObject and test/MyObject). Will it always look first in test folders and only then go to the src one, regardless of 'distance' to the original project?). In other words-will unit test runs always look for src/test first, and 'production' runs always look for 'src/main'-regardless of them being in any jar/dependency path? – iddqd Nov 14 '16 at 11:38
  • src/test will not be seen from any other project so there is no risk of those classes/resources being used in the production code. They will also never be seen if an external project has a dependency to your project. As long as your unit tests are located in src/test(which they should be) they will always prioritize resources from src/test. – AleSod Nov 14 '16 at 12:44