Spring 启动集成测试 - Maven 测试缺少 JSTL

Spring Boot Integration Test - Maven Tests missing JSTL

我正在尝试使用 Selenium 为我们的应用程序实施集成测试。我们的想法是加载我们 SpringMVC 项目的 applicationcontext,启动一个嵌入式 Tomcat 容器,然后对其进行 运行 集成测试,然后关闭并完成应用程序编译。

现在 运行从 Eclipse 中进行 JUnit 测试以 Spring 完美启动服务器,但是当 运行ning Maven 测试和访问网站时(通过或不通过 Selenium) ),我得到以下异常:

org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

但是,JSTL 在 Maven 中范围 test 的类路径中。有谁知道,为什么会这样?

我的配置分为一个父项目,一个用于我们项目的内部库,另一个用于实际项目。我省略了 pom.xml:

中无趣的部分
<properties>
    <apache.tiles.version>3.0.4</apache.tiles.version>
    <tomcat.version>7.0.59</tomcat.version>
</properties>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-jsp</artifactId>
    <version>${apache.tiles.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-core</artifactId>
    <version>${apache.tiles.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-api</artifactId>
    <version>${apache.tiles.version}</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.3.1</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.2.8</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>${spring.boot.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.47.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-el</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-logging-juli</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-websocket</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <version>${tomcat.version}</version>
    <scope>test</scope>
</dependency>

TestConfig.java:

@EnableAutoConfiguration
@SpringBootApplication
@Import({ GVAppConfiguration.class, SecSecurityConfig.class, TestMvcConfig.class })
@ImportResource({ "classpath:applicationContext.xml", "classpath:/META-INF/applicationContext-commons.xml",
    "classpath:/applicationContext-solr.xml" })
public class TestConfig extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
    return application.sources(TestConfig.class);
    }

    public static void main(final String[] args) {
    SpringApplication.run(TestConfig.class);
    }
}

IndexControllerTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
@WebIntegrationTest(value = "server.port=9000")
@SeleniumTest(driver = FirefoxDriver.class, baseUrl = "http://localhost:9000")
public class IndexControllerTest {

    @Autowired
    private WebDriver webDriver;

    @Test
    public void testController() {
    webDriver.getTitle();
    }

}

像这样尝试 deps :

<groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

事实证明,默认情况下,Maven 的 Surefire 插件采用了一种技巧,它创建了一个 Manifest-Only JAR 文件,以避免需要将完整的类路径传递给分叉的 JRE(请参阅本文)。 Jetty JSP 处理器只是向每个类加载器询问其 URL 列表,因此只能看到一个仅包含清单的 JAR 文件,而不是实际使用的所有 JAR 文件,因此找不到 TLD文件。

该页面上也有记录的简单解决方案是关闭 useManifestOnlyJar 选项,如下所示:

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.18.1</version>
    <configuration>
      <useManifestOnlyJar>false</useManifestOnlyJar>
    </configuration>
  </plugin>
  ....
<plugin>

这指示 Surefire 将完整的类路径直接传递给分叉的 JRE 进程,从而允许它定位 TLD。 已回答 from here.