In my code I need to do certain fixes only when it is run inside a JUnit test. How can I find out if code is running inside a JUnit test or not? Is there something like JUni
this is not strictly related to the user question, but I'm pretty sure that someone that get there may find it useful.
I use the following approach: expose a package-local constructor that will be used from tests.
e.g.
src/main/java/ApplicationService.java
public class ApplicationService {
private final Integer someInternalObject;
public ApplicationService(String somePublicArgument) throws NumberFormatException {
someInternalObject = Integer.valueOf(somePublicArgument, 16);
}
ApplicationService(Integer someInternalObject) {
this.someInternalObject = someInternalObject;
}
}
src/test/ApplicationServiceTest.Java
public class ApplicationServiceTest {
@Test
public void testSomething() throws Exception {
ApplicationService applicationService = new ApplicationService(0);
}
}
Extend it in the tests and provide a public constructor for the package-local or protected one.
Make a public Factory Method in the same package ( within tests ) that will create it using the package-local constructor.
It might be a good idea if you want to programmatically decide which "profile" to run. Think of Spring Profiles for configuration. Inside an integration tests you might want to test against a different database.
Here is the tested code that works
public static boolean isJUnitTest() {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().startsWith("org.junit.")) {
return true;
}
}
return false;
}
How about checking if the junit jar is in the classpath?
If you're doing things differently because you're doing a unit test you're defeating the purpose of a unit test. A unit test is supposed to perform exactly like production would (except for the setup and teardown of any necessary data and such you need....but that is included in the JUnit test itself and not your code).
However, if you truly do have a good reason for this I'd look at the stack and see if JUnit is there.
When using Spring one can define a bean which holds this value.
In application context:
@Bean
public boolean isRunningTests() {
return false;
}
In test application context:
@Bean
public boolean isRunningTests() {
return true;
}
Inject the value to a Spring component:
@Resource
private boolean isRunningTests;
private void someMethod() {
if (isRunningTests()) {
....
The shortest (least code) solution is to have a global flag that is set when tests are not running. You can then set it once in your main()
(or similar entry point) instead of setting it repeatedly in setup methods of all test classes. This will work as long as there is no other way to enter the code (no alternate main
).
The second shortest solution is to scan the call stack for junit package like in Janning's answer. This will work as far as junit doesn't hide itself behind another library and an executor.
Dependency injection will work too, but in this case it's just a fancy way to set what's essentially a global flag.