Kotlin - Maven 不执行测试
Kotlin - Maven not executing tests
我有一个要测试的 Kotlin 应用程序。我的测试 (.kt
) 文件在 Eclipse 中成功执行。 (测试本身是一个 h2 mock
jdbc 测试)。
现在 运行 mvn test -X
它说:
releases: [enabled => true, update => never]
]
[DEBUG] (s) reportFormat = brief
[DEBUG] (s) reportsDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\target\surefire-reports
[DEBUG] (f) rerunFailingTestsCount = 0
[DEBUG] (f) reuseForks = true
[DEBUG] (s) runOrder = filesystem
[DEBUG] (f) shutdown = testset
[DEBUG] (s) skip = false
[DEBUG] (f) skipAfterFailureCount = 0
[DEBUG] (s) skipTests = false
[DEBUG] (s) suiteXmlFiles = []
[DEBUG] (s) testClassesDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\target\test-classes
[DEBUG] (s) testFailureIgnore = false
[DEBUG] (s) testNGArtifactName = org.testng:testng
[DEBUG] (s) testSourceDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\src\test\java
[DEBUG] (s) threadCountClasses = 0
[DEBUG] (s) threadCountMethods = 0
[DEBUG] (s) threadCountSuites = 0
[DEBUG] (s) trimStackTrace = true
[DEBUG] (s) useFile = true
[DEBUG] (s) useManifestOnlyJar = true
[DEBUG] (s) useSystemClassLoader = true
[DEBUG] (s) useUnlimitedThreads = false
[DEBUG] (s) workingDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete
[DEBUG] (s) project = MavenProject: org.springframework:gs-rest-service:0.1.0 @ C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\pom.xml
它不执行任何测试(它找不到 em)
这是我的 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- <dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1211</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.191</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect -->
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.0.3</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version><!--$NO-MVN-MAN-VER$ -->
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version><!--$NO-MVN-MAN-VER$-->
<configuration>
<includes>
<include>**/Test*.kt</include>
<include>**/*Test.kt</include>
<include>**/*TestCase.kt</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
两个问题,第一个问题你自己找的,但我会在这里记录。在 Kotlin-Maven 插件中,您将 test-compile
目标设置为:
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
它正在编译 src/main/java
目录而不是 src/test/java
,因此您的测试根本不会被编译。应该是:
<sourceDirs>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
或者如果您的文件同时位于 java
和 kotlin
目录中:
<sourceDirs>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
</sourceDirs>
第二个问题您可能正在尝试解决第一个问题。表面上看起来不错,但 Surefire 插件的配置不正确。 Maven Surefire 插件的文档不是很准确(或者它的工作原理并不完整)。如果你完全删除你的 Surefire 插件配置,它就会工作,因为默认设置已经做了你想要的。或者,您可以将 include
文件模式从 .kt
后缀改为 .class
或 .java
后缀,即使对于 Kotlin、Clojure、Scala,这些也能正常工作, ...
为什么?这是故事...
此配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*TestCase.java</include>
<include>**/RandomName.java</include>
</includes>
</configuration>
</plugin>
并不像您认为的那样。这实际上是通过在 .java
上搜索并替换为 .class
在 Surefire 中转换为:
<configuration>
<includes>
<include>**/Test*.class</include>
<include>**/*Test.class</include>
<include>**/*TestCase.class</include>
<include>**/RandomName.class</include>
</includes>
</configuration>
但是,如果您使用 .kt
扩展程序,您就会破坏这种硬编码的魔法。您可以在 source code of Surefire plugin 中看到它,它将以 .java
结尾的文件替换为 .class
。 糟糕,它与源文件完全无关,正在寻找已编译的 classes.
在 Surefire 插件 2.19
中,他们添加了 regex and also fully qualified classname patterns 的能力。所以插件决定你使用哪个的方式似乎是由文件扩展名.java
决定的。如果它看到 .java
,它就知道每个 .java
文件都会变成同名的 class,因此它会查找与模式匹配的 classes,而不是源文件代码。源代码已经由编译器插件编译,而不是测试运行器。它与寻找源代码无关。
所以此设置具有误导性,实际上是使用 "magic" 计算出 class 名称,而不是仅仅询问 class 名称。当然,示例和所有内容完全让您相信它与源文件有关。不是。
最好不使用任何配置并遵循默认命名约定。或者,如果您必须指定某些内容,请使用更现代的正则表达式或 include
配置的 class 名称版本:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>Test*</include>
<include>*Test</include>
<include>*TestCase</include>
<include>RandomName</include>
</includes>
</configuration>
</plugin>
现在正在与任何包中具有这些名称的任何 class 进行比较。
我有一个要测试的 Kotlin 应用程序。我的测试 (.kt
) 文件在 Eclipse 中成功执行。 (测试本身是一个 h2 mock
jdbc 测试)。
现在 运行 mvn test -X
它说:
releases: [enabled => true, update => never]
]
[DEBUG] (s) reportFormat = brief
[DEBUG] (s) reportsDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\target\surefire-reports
[DEBUG] (f) rerunFailingTestsCount = 0
[DEBUG] (f) reuseForks = true
[DEBUG] (s) runOrder = filesystem
[DEBUG] (f) shutdown = testset
[DEBUG] (s) skip = false
[DEBUG] (f) skipAfterFailureCount = 0
[DEBUG] (s) skipTests = false
[DEBUG] (s) suiteXmlFiles = []
[DEBUG] (s) testClassesDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\target\test-classes
[DEBUG] (s) testFailureIgnore = false
[DEBUG] (s) testNGArtifactName = org.testng:testng
[DEBUG] (s) testSourceDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\src\test\java
[DEBUG] (s) threadCountClasses = 0
[DEBUG] (s) threadCountMethods = 0
[DEBUG] (s) threadCountSuites = 0
[DEBUG] (s) trimStackTrace = true
[DEBUG] (s) useFile = true
[DEBUG] (s) useManifestOnlyJar = true
[DEBUG] (s) useSystemClassLoader = true
[DEBUG] (s) useUnlimitedThreads = false
[DEBUG] (s) workingDirectory = C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete
[DEBUG] (s) project = MavenProject: org.springframework:gs-rest-service:0.1.0 @ C:\Users\Ivar\workspace\anotherworkspace\newrestservice\complete\pom.xml
它不执行任何测试(它找不到 em)
这是我的 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- <dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1211</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.191</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-reflect -->
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.0.3</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version><!--$NO-MVN-MAN-VER$ -->
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version><!--$NO-MVN-MAN-VER$-->
<configuration>
<includes>
<include>**/Test*.kt</include>
<include>**/*Test.kt</include>
<include>**/*TestCase.kt</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
两个问题,第一个问题你自己找的,但我会在这里记录。在 Kotlin-Maven 插件中,您将 test-compile
目标设置为:
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
它正在编译 src/main/java
目录而不是 src/test/java
,因此您的测试根本不会被编译。应该是:
<sourceDirs>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
或者如果您的文件同时位于 java
和 kotlin
目录中:
<sourceDirs>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
</sourceDirs>
第二个问题您可能正在尝试解决第一个问题。表面上看起来不错,但 Surefire 插件的配置不正确。 Maven Surefire 插件的文档不是很准确(或者它的工作原理并不完整)。如果你完全删除你的 Surefire 插件配置,它就会工作,因为默认设置已经做了你想要的。或者,您可以将 include
文件模式从 .kt
后缀改为 .class
或 .java
后缀,即使对于 Kotlin、Clojure、Scala,这些也能正常工作, ...
为什么?这是故事...
此配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*TestCase.java</include>
<include>**/RandomName.java</include>
</includes>
</configuration>
</plugin>
并不像您认为的那样。这实际上是通过在 .java
上搜索并替换为 .class
在 Surefire 中转换为:
<configuration>
<includes>
<include>**/Test*.class</include>
<include>**/*Test.class</include>
<include>**/*TestCase.class</include>
<include>**/RandomName.class</include>
</includes>
</configuration>
但是,如果您使用 .kt
扩展程序,您就会破坏这种硬编码的魔法。您可以在 source code of Surefire plugin 中看到它,它将以 .java
结尾的文件替换为 .class
。 糟糕,它与源文件完全无关,正在寻找已编译的 classes.
在 Surefire 插件 2.19
中,他们添加了 regex and also fully qualified classname patterns 的能力。所以插件决定你使用哪个的方式似乎是由文件扩展名.java
决定的。如果它看到 .java
,它就知道每个 .java
文件都会变成同名的 class,因此它会查找与模式匹配的 classes,而不是源文件代码。源代码已经由编译器插件编译,而不是测试运行器。它与寻找源代码无关。
所以此设置具有误导性,实际上是使用 "magic" 计算出 class 名称,而不是仅仅询问 class 名称。当然,示例和所有内容完全让您相信它与源文件有关。不是。
最好不使用任何配置并遵循默认命名约定。或者,如果您必须指定某些内容,请使用更现代的正则表达式或 include
配置的 class 名称版本:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>Test*</include>
<include>*Test</include>
<include>*TestCase</include>
<include>RandomName</include>
</includes>
</configuration>
</plugin>
现在正在与任何包中具有这些名称的任何 class 进行比较。