如何判断代码是否在JUnit测试中运行?

时间:2010-02-26 13:37:40

标签: java junit

在我的代码中,我需要在JUnit测试中运行时才进行某些修复。如何判断代码是否在JUnit测试中运行?有没有类似JUnit.isRunning()== true的东西?

11 个答案:

答案 0 :(得分:46)

如果您想以编程方式决定运行哪个“配置文件”,这可能是个好主意。想一想Spring Profiles的配置。在集成测试中,您可能希望针对不同的数据库进行测试。

这是经过测试的代码

public static boolean isJUnitTest() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    List<StackTraceElement> list = Arrays.asList(stackTrace);
    for (StackTraceElement element : list) {
        if (element.getClassName().startsWith("org.junit.")) {
            return true;
        }           
    }
    return false;
}

答案 1 :(得分:23)

首先,这可能不是一个好主意。您应该对实际生产代码进行单元测试,而不是稍微不同的代码。

如果你真的想这样做,你可以查看堆栈跟踪,但是既然你正在改变你的程序,你也可以在你的代码中引入一个新的静态布尔字段isUnitTesting,让JUnit将此设置为true。保持简单。

答案 2 :(得分:16)

在这个帖子上有很多人说,在JUnit下,代码运行方式略有不同是个坏主意。我普遍同意,但我认为有一些例外。

例如,我目前正在为连接到数据库的应用程序编写INTEGRATION(而不是Unit)测试。

这些验收测试通常需要使用特定的测试数据完全重新初始化DB。

显然,我不希望这样,甚至不能在实际的生产数据库上完成,因为这可能会完全抹掉有价值的生产数据。

保证永远不会发生这种情况的最简单方法是使代码在JUnit下运行时无法连接到生产数据库。例如,如果生成连接的Factory可以告诉它在JUnit下运行,那么这反过来就可以完成,在这种情况下,除非我们尝试连接的数据库具有已知的名称,否则将返回空连接成为测试数据库(例如:“testdatabase”)。

答案 3 :(得分:10)

我可以为此找到理由,当您想要在生产类中提供代码以帮助测试时。这类似于Java断言,它仅在设置调试标志时适用。

这样的事情:

Object debugState() {
    // This is only meant to be called when testing
    if (!JUnit.isRunning()) {
        throw new IllegalStateException("Not in a test!");
    }
    // Now compute possibly costly debug information
    // not to be used in production
    Object state = ...
}

答案 4 :(得分:4)

如果你做的事情不同,因为你正在进行单元测试,那么你就会失去单元测试的目的。单元测试应该完全像生产一样执行(除了设置和拆除任何必要的数据之外,你需要......但是它包含在JUnit测试本身而不是你的代码中)。

但是,如果你确实有充分的理由,我会查看堆栈,看看是否有JUnit。

答案 5 :(得分:4)

检查junit jar是否在类路径中怎么样?

答案 6 :(得分:2)

使用Spring时,可以定义一个保存该值的bean。

在应用程序上下文中:

@Bean
public boolean isRunningTests() {
    return true;
}

在测试应用程序上下文中:

@Resource
private boolean isRunningTests;

private void someMethod() {
    if (isRunningTests()) {
        ....

将值注入Spring组件:

{{1}}

答案 7 :(得分:0)

为了区分test和no test,你总是可以在application-test.properties中定义特殊属性或值。

答案 8 :(得分:0)

最短(最少代码)解决方案是在测试运行时设置全局标志。然后,您可以在main()(或类似的入口点)中设置一次,而不是在所有测试类的设置方法中重复设置它。只要没有其他方式输入代码(无替代main),这将有效。

第二个最短的解决方案是扫描调用堆栈中的junit包,如Janning's answer中所示。这将是有效的,因为junit不会隐藏在另一个库和执行者之后。

依赖注入也会起作用,但在这种情况下,它只是一种奇特的方式来设置本质上是一个全局标志。

答案 9 :(得分:0)

这对我有用:

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

它可以用于Maven测试以及Eclipse IDE内部,只要将junit作为范围“ test”的依赖项包括在内,例如:

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

答案 10 :(得分:-1)

这与用户问题并不严格相关,但我非常确定那些到达那里的人可能会觉得它很有用。

我使用以下方法:公开将在测试中使用的包本地构造函数。

e.g。

  

的src /主/爪哇/ 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 /测试/ ApplicationServiceTest.Java

public class ApplicationServiceTest {
  @Test
  public void testSomething() throws Exception {
    ApplicationService applicationService = new ApplicationService(0);
  }
}

将其暴露给所有测试

不是最后的课程

在测试中扩展它,并为包本地或受保护的包提供公共构造函数。

最后的课程

在同一个包中(在测试中)使用package-local构造函数创建一个公共Factory Method