Reputation: 1305
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!
Upvotes: 3
Views: 2205
Reputation: 422
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.
Upvotes: 4