在Jar中打包后,SpringJUnit4ClassRunner无法正常工作但在IDE

时间:2017-11-29 18:24:34

标签: java spring junit junit4

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

这些测试用例有一个父类,它正在加载spring上下文。

@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 { }

使用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 plugin 3.0来打包jar。

编辑1
执行jar as -

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实例。 这些被包装为测试用例的原因是因为理想情况下我们想要将它与酱油相结合(酱油需要包含硒代码作为测试用例进行执行。)但是,目前对于如何设置酱油有一些限制在我的组织中,我们无法在今天走这条路,但在我们解决这个问题时,我们一直在编写这段代码。所以现在,我正在尝试使用此代码创建一个JAR并将其部署到生产环境中。这样,当我们能够使用Saucelabs移动时,我不必做出很多改变。

1 个答案:

答案 0 :(得分:1)

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

  1. 将项目更改为spring boot,启用自动配置并使用spring boot maven插件创建JAR,该插件负责正确打包。
  2. spring.factories中创建src/main/resources/META-INF文件。您可以从项目中的任何spring依赖项编写自己的(refer spring doc)或复制spring.factoriesRelated question on SO
  3. 我选择了2,因为在这种情况下看起来很容易。我不需要弹簧启动依赖项中的spring.factories,因此选项1本来就是一种过度杀伤。