How can I find out if code is running inside a JUnit test or not?

JavaJunit

Java Problem Overview


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 JUnit.isRunning() == true ?

Java Solutions


Solution 1 - Java

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;
}

Solution 2 - Java

First of all, this a probably not a good idea. You should be unit testing the actual production code, not slightly different code.

If you really want to do this, you could look at the stacktrace, but since you are changing your program for this anyway, you might just as well introduce a new static boolean field isUnitTesting in your code, and have JUnit set this to true. Keep it simple.

Solution 3 - Java

Lots of people on this thread say that it's a bad idea for code to run slightly differently while under JUnit. I generally agree, but I think there are some exceptions.

For example, I am currently writing INTEGRATION (as opposed to Unit) tests for an app that connects to a DB.

These acceptance tests often need to completely reinitialize the DB with specific test data.

Obviously, I don't want this EVER, EVER to be done on an actual production DB, because that might completely erase valuable production data.

The easiest way to guarantee that this will never happen, is to make it impossible for the code to connect to a production DB when it is running under JUnit. This in turn can be done if, for example, the Factory that generates a connection can tell that it's running under JUnit, and in that case, will return a null connection unless the database we are trying to connect to has a name that is known to be a test database (ex: "testdatabase").

Solution 4 - Java

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.

Solution 5 - Java

This has worked for me:

private Boolean isRunningTest = null;

private boolean isRunningTest() {
	if (isRunningTest == null) {
		isRunningTest = true;
		try {
			Class.forName("org.junit.Test");
		} catch (ClassNotFoundException e) {
			isRunningTest = false;
		}
	}
	return isRunningTest;
}

It can be used in Maven tests, as well as inside the Eclipse IDE, as long as junit is included as a dependency with scope "test", eg:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>${junit.version}</version>
	<scope>test</scope>
</dependency>

Solution 6 - Java

How about checking if the junit jar is in the classpath?

Solution 7 - Java

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()) {
        ....

Solution 8 - Java

In order to distinguish between test and no test you can always define special property or value in application-test.properties.

Solution 9 - Java

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.

Solution 10 - Java

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);
  }
}

expose it to all tests

not final classes

Extend it in the tests and provide a public constructor for the package-local or protected one.

final classes

Make a public Factory Method in the same package ( within tests ) that will create it using the package-local constructor.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDr. Max V&#246;lkelView Question on Stackoverflow
Solution 1 - JavaJanningView Answer on Stackoverflow
Solution 2 - JavaThiloView Answer on Stackoverflow
Solution 3 - JavaAlain DésiletsView Answer on Stackoverflow
Solution 4 - JavaSOA NerdView Answer on Stackoverflow
Solution 5 - JavaAndrea MView Answer on Stackoverflow
Solution 6 - JavaDerropsView Answer on Stackoverflow
Solution 7 - JavaMilankaView Answer on Stackoverflow
Solution 8 - JavaMeir G.View Answer on Stackoverflow
Solution 9 - JavaRobert VažanView Answer on Stackoverflow
Solution 10 - Javatux_mindView Answer on Stackoverflow