【问题标题】:SpringJUnit4ClassRunner not working after packaging in Jar but works in IDESpringJUnit4ClassRunner 在 Jar 中打包后不工作,但在 IDE 中工作
【发布时间】:2017-11-29 18:24:34
【问题描述】:

我将 JUnit 测试用例和套件打包到一个 jar 中,并尝试使用 JUnit 核心从 main 内部执行这些。问题是当我在 JAR 中打包后执行这些测试用例时,没有注入 bean(这意味着 spring 上下文存在问题。)但是,当我从 IDE 执行 main 方法时,注入了 bean 并且一切正常。

这些测试用例有一个加载弹簧上下文的父类。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { AppConfig.class } )
public abstract class BaseTest {

    @Autowired
    protected WebDriver driver;

    @PreDestroy
    public void teardown() {
        ...
    }
}

一个测试类和套件-

public class SomeTestClass extends BaseTest {
    @Test
    public void someTestCase() {
        ...
    }
}


@RunWith(Suite.class)
@Suite.SuiteClasses({
    SomeTestClass.class
})
public class SomeTestSuite { }

有一个 main 方法用于使用 JUnitCore 执行这些测试用例/套件。

    public static void main(String...args) {
        Result result = JUnitCore.runClasses(SomeTestSuite.class);

        if (result.wasSuccessful()) {
            LOGGER.info("All tests executed successfully: {}", result);
        } else {
            LOGGER.error("There are failures");
            for (Failure failure: result.getFailures()) {
                LOGGER.error("failure: {} msg: {} desc: {}", failure, failure.getMessage(), failure.getDescription(), failure.getException());
            }
        }
    }

我在通过 JAR 执行此操作时收到 NullPointerException,但在 IDE 中执行 main 方法时没有问题。
我使用 IntelliJ 2017.2.x、JUnit 4.12 测试用例和 maven shade 插件 3.0 来打包 jar。

编辑 1
执行 jar 为 -

java -jar myjar.jar

通过 JAR 执行时的 NPE-

2017-11-29 10:16:00,567 [TestCasesExecutor:44] ERROR junit.framework.Test  - failure: testMethodName(testClass): null msg: null desc: testMethodName(testClass)
java.lang.NullPointerException
        at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:770)
        at org.openqa.selenium.support.ui.FluentWait.<init>(FluentWait.java:96)
        at org.openqa.selenium.support.ui.WebDriverWait.<init>(WebDriverWait.java:71)
        at org.openqa.selenium.support.ui.WebDriverWait.<init>(WebDriverWait.java:45)
        at com.mycom.SomeTestClass.setup(BaseTest.java:37)
        at com.mycom.testcases.SplunkGcpScoreCardTest.logoutFromGcpScorecard(SplunkGcpScoreCardTest.java:27)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
        at org.junit.runners.Suite.runChild(Suite.java:128)
        at org.junit.runners.Suite.runChild(Suite.java:27)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.junit.runners.Suite.runChild(Suite.java:128)
        at org.junit.runners.Suite.runChild(Suite.java:27)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:105)
        at org.junit.runner.JUnitCore.runClasses(JUnitCore.java:62)
        at org.junit.runner.JUnitCore.runClasses(JUnitCore.java:49)
        at com.mycom.TestCasesExecutor.main(TestCasesExecutor.java:37)

背景 - 我有一些用于生产应用程序的 selenium 测试用例。它创建了一个用于执行的无头 chrome 实例。 将这些包装为测试用例的原因是因为理想情况下我们希望将其与 saucelabs 集成(saucelabs 需要将 selenium 代码包装为测试用例才能执行。)但是,目前对于如何设置 saucelabs 存在一些限制在我的组织中,我们今天还不能走这条路,但是当我们弄清楚这一点时,我们一直在编写这段代码。所以现在,我正在尝试使用此代码创建一个 JAR 并将其部署到生产中。这样一来,当我们能够与 Saucelabs 一起移动时,我不必进行太多更改。

【问题讨论】:

  • 我认为您的单元测试不属于任何可执行的 JAR。它们应该在打包之前在您的 IDE 或集成构建工具中运行。
  • 我的情况不同。这些是业务 Web 应用程序的 selenium 测试用例。尽管我很想将这些与酱实验室集成,但目前它不是一个选项。
  • 对我来说听起来并没有什么不同。祝你好运。堆栈跟踪告诉你什么是空的。这会给你一个提示。
  • 粘贴您的 NPE 和您获得的任何其他日志输出。粘贴您如何“通过 JAR”运行此程序。并解释为什么你甚至想从 jar 中运行打包在 main 中的 junit 测试,而不是使用 maven。
  • NPE 粘贴在上面,JAR 被触发为“java -jar myjar.jar”。当代码使用来自 spring 核心的 Environment 类型的对象时,就会发生 NPE。它应该是Autowired。我打印了要自动装配的班级成员,他们都是空的。

标签: java spring junit junit4


【解决方案1】:

通过 spring 代码和日志进行故障排除后,我认为它失败了,因为 我的 JAR 的 META-INF 中没有 spring.factories 文件。 可能的解决方案 -

  1. 将项目更改为 spring boot,启用自动配置并使用 spring boot maven 插件创建一个 JAR,该插件负责正确打包它。
  2. src/main/resources/META-INF 中创建spring.factories 文件。您可以编写自己的 (refer spring doc) 或从项目中的任何 spring 依赖项中复制 spring.factoriesRelated question on SO

我选择了选项 2,因为在这种情况下看起来很容易。我只需要来自 spring-boot 依赖项的 spring.factories 之外的任何东西,所以选项 1 将是一个矫枉过正。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 2013-08-06
    • 1970-01-01
    • 2015-11-06
    • 2014-05-07
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多