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

Dr.*_*kel 54 java junit

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

Jan*_*ing 53

如果您想以编程方式决定运行哪个"配置文件",这可能是个好主意.想一想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;
}
Run Code Online (Sandbox Code Playgroud)

  • 您还需要缓存结果,因为对于给定的执行,该值永远不会改变。 (3认同)
  • 我们需要为 JUnit 测试配置不同的数据库环境。 (2认同)
  • for (StackTraceElement 元素: currentThread().getStackTrace()) { (2认同)

Thi*_*ilo 25

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

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

  • 想到它,这有点像依赖注入.他应该为难以测试的依赖项注入模拟对象,但我认为明确地将布尔值设置为true仍然比尝试让类自己解决它更好. (5认同)
  • “您应该对实际的生产代码进行单元测试”。没有人这样做。单元测试几乎总是使用某种形式的模拟,通常通过多态性(即接口)来实现。使用标志只是做同样事情的另一种方式。差异是风格上的,而且相对来说并不明显。 (2认同)

小智 16

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

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

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

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

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

  • 这可以通过使您的代码不了解生产数据库来解决.它将使用环境变量或特定位置中的任何配置.生产配置可能是一个不为人熟知的配置(即仅存在于部署中,而不存在于版本控制中).这不仅更安全,而且还解决了测试问题,无需修改生产代码. (3认同)

Jai*_*aiz 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 = ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这证明了这个问题,但没有回答 (3认同)

小智 10

这对我有用:

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;
}
Run Code Online (Sandbox Code Playgroud)

它可以在 Maven 测试中使用,也可以在 Eclipse IDE 中使用,只要将 junit 包含为范围为“test”的依赖项即可,例如:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)


SOA*_*erd 6

如果您因为进行单元测试而以不同的方式做事,那么您就违背了单元测试的目的。单元测试应该像生产一样执行(除了任何必要数据的设置和拆卸以及您需要的数据......但这包含在 JUnit 测试本身而不是您的代码中)。

但是,如果您确实有充分的理由这样做,我会查看堆栈并查看是否有 JUnit。


Mil*_*nka 5

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

在应用程序上下文中:

@Bean
public boolean isRunningTests() {
    return false;
}
Run Code Online (Sandbox Code Playgroud)

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

@Bean
public boolean isRunningTests() {
    return true;
}
Run Code Online (Sandbox Code Playgroud)

将值注入到 Spring 组件中:

@Resource
private boolean isRunningTests;

private void someMethod() {
    if (isRunningTests()) {
        ....
Run Code Online (Sandbox Code Playgroud)


Sni*_*192 5

如何检查 junit jar 是否在类路径中?