我有提供网络服务的 webapp。我想使用 SoapUI 执行 JUnit 测试以检查此服务是否正常工作。
但是要测试 Web 服务应用程序必须部署到我的 Tomcat 7 服务器。
我不知道如何配置 maven 来构建战争,然后将其部署到 tomcat(理想情况下:为此运行单独的 tomcat 实例),然后运行 JUnit 测试。
我将不胜感激。
我正在使用 Maven 2.2.1
关于如何使用 Maven处理这种类型的集成测试,有许多思想流派。
我应该指出,当您将应用程序部署到应用程序服务器时,您不再处于单元测试领域。因为整个应用程序都部署在一个容器中,所以您正在测试这两个组件的集成。
现在使用 JUnit 运行集成测试没有任何问题(尽管您可能会遇到一些限制,例如单元测试不应该关心单个测试的顺序 - 假设您正确编写它们 - 所以 JUnit通过不强制执行此操作保证任何执行顺序...在 Java 1.7 之前,执行顺序是由类中测试方法的顺序意外暗示的,但它不是 JUnit 合同的一部分...有些人切换到其他测试框架进行集成测试,例如 TestNG,如果他们发现 JUnit 的单元测试重点妨碍了他们的测试开发)
要记住的关键点是 Maven 生命周期使用test
阶段来执行单元测试。
谈到集成测试,关于使用 Maven 处理测试的正确方法,有两种(半)思想流派。
integration-test/verify
这种思想流派使用之后的阶段package
来启动容器,运行集成测试,拆除容器,最后检查测试结果并在测试失败时使构建失败。
永远不要运行mvn integration-test
,因为这不会正确地拆除容器,任何时候你认为你想输入mvn integration-test
你真的想输入mvn verify
(哦,看,它更短更容易输入......奖金)
因此,您可以执行以下操作:
pre-integration-test
阶段fork
=true
integration-test
阶段post-integration-test
阶段verify
阶段。对于额外的布朗尼点,您将使用build-helper-maven-plugin:reserve-network-port绑定到validate
阶段以确保测试服务器在未使用的网络端口上启动,然后对测试资源使用资源过滤以通过端口通过测试或使用通过systemPropertyVariables传递的系统属性使端口号可用于测试。
run-its
如果测试太慢而无法运行每个构建,则可以将集成测试移动到单独的配置文件中(按照约定称为)。IT
,虽然 Maven 知道以Test
Surefire 开始/结束运行测试并IT
以 Failsafe 开始/结束运行测试,但您的 IDE 可能不知道。此外,您的 IDE 不会为您启动容器,因此您必须手动完成大量工作才能真正手动运行测试。调试测试可能需要附加两个调试器,例如一个用于调试在容器中运行的应用程序,另一个用于调试测试用例。
mvnDebug -Dmaven.failsafe.debug=true verify
将您的测试与 Maven 构建过程相结合。
这种思想流派将集成测试移动到一个独立的模块中,该模块依赖于该模块,并使用例如绑定到与Tomcat7 依赖项相结合的阶段将其war
复制到测试资源中以进行测试。war
dependency:copy-dependencies
generate-test-resources
测试用例本身使用嵌入式模式启动 Tomcat7 容器
war
才会重建工件package
,因此,在使用 IDE 时,您需要至少mvn clean package
定期运行以刷新被测代码。war
模块的构建,因此您最终可以释放一个损坏的war
工件,然后让集成测试模块的反应器构建失败。有些人通过在其中包含集成测试模块src/it
并使用 Maven Invoker 插件来运行测试来解决这个问题......虽然这提供了较差的 IDE 集成,所以我不推荐这条线。这是两种方法的一种混合。
您使用 Failsafe 执行测试,但测试本身负责启动和停止您要测试的 Tomcat7 容器。
我希望以上内容可以帮助您了解您拥有的选项。可能还有其他调整,但总的来说,以上被认为是目前与 Maven 进行集成测试的最佳实践。
@Stephen Connolly - 你上面的答案非常好。我想我会开始并为您所谓的School 1
响应显示完整的配置。
这个配置:
@Category
单元测试和集成测试扩展的根类上的注释。那里还有其他内容,例如如何仅在依赖应用程序上设置某些系统属性。
到目前为止,这个配置工作得很棒..
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<portNames>
<portName>tomcat.maven.http.port</portName>
</portNames>
</configuration>
</execution>
<execution>
<id>get-local-ip</id>
<goals>
<goal>local-ip</goal>
</goals>
<configuration>
<!-- if not given, 'local.ip' name is used -->
<localIpProperty>local.ip</localIpProperty>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- http port from reserve-network-port-plugin-->
<port>${tomcat.maven.http.port}</port>
<!-- application path always starts with /-->
<path>/</path>
<webapps>
<webapp>
<groupId>com.company.other.app</groupId>
<artifactId>web-rest</artifactId>
<version>1.0.1-SNAPSHOT</version>
<type>war</type>
<contextPath>/webapi-loopback</contextPath>
<asWebapp>true</asWebapp>
</webapp>
</webapps>
</configuration>
<executions>
<execution>
<id>start-server</id>
<configuration>
<fork>true</fork>
<skip>${skipTests}</skip>
<systemProperties>
<spring.profiles.active>test,h2</spring.profiles.active>
</systemProperties>
</configuration>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<configuration>
<skip>${skipTests}</skip>
</configuration>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<excludedGroups>com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory</excludedGroups>
</configuration>
<executions>
<execution>
<id>unit-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m @{jacocoArgLine}</argLine>
<excludedGroups> com.company.app.service.IntegrationTestRootClassAnnotatedWithAtCategory </excludedGroups>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.18</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>start-integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m @{jacocoArgLine}</argLine>
<groups>com.company.app.IntegrationTestRootClassAnnotatedWithAtCategory</groups>
<includes>
<include>**/*.java</include>
</includes>
<systemPropertyVariables>
<program.service.url>
http://${local.ip}:${tomcat.maven.http.port}/webapi-loopback
</program.service.url>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
正如 Stephen Connolly 解释的那样,没有直接的方法来配置它。我将解释如何使用故障安全插件解决这个问题。在maven生命周期类型的测试中可以进行测试。其中一个是单元测试,另一个是集成测试。单元测试可以在 maven 生命周期的测试阶段运行。当您想做集成测试时,可以在验证阶段完成。如果您想知道单元测试和集成测试之间的区别,这是一个很好的。默认情况下,单元测试类应该是***/*Test.java
, 和**/*TestCase.java
这种格式。故障保护插件将查找**/IT*.java
、**/*IT.java
和**/*ITCase.java
。
这里我有一个单元测试类和一个集成测试类。现在我将解释一下,maven pom.xml 的样子应该如何。Maven 配置的构建部分应如下所示。
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<warName>${name}</warName>
<outputDirectory>/home/jobs/wso2/wso2as-5.3.0/repository/deployment/server/webapps</outputDirectory>
<goal>
</goal>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
单元测试在部署 web 应用程序(war 文件)之前运行。但是集成测试在验证阶段运行。我希望你的要求在这个阶段得到满足。