首页 > 解决方案 > 使用 docker 容器的 Spring Boot 集成测试多模块 maven 应用程序

问题描述

我有一个使用 Spring Boot 的多模块 Maven 应用程序。它定义了 Rest API 来为消费者提供服务。

在我的模块 1 中 pom 中的 Spring boot maven 插件配置如下

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.5.4.RELEASE</version>
    <configuration>
        <mainClass>com.package.Application</mainClass>
        <layout>JAR</layout>
    </configuration>
     <executions>
        <execution>
            <goals>
                <goal>repackage</goal> 
            </goals>
            <configuration>
                <classifier>exec</classifier>
            </configuration> 
        </execution> 
    </executions>
</plugin>   

我正在使用 fabric io 创建 docker 映像。见下文我的模块 1 中的 fabric io 插件定义

<plugin>
    <groupId>io.fabric8</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.24.0</version>           
    <configuration>         
        <images>
            <image>         
                <alias>service</alias>
                <name>Sample</name>         
                <build>         
                    <from>greyfoxit/alpine-openjdk8</from>
                    <entryPoint>
                        <exec>
                            <arg>java</arg>
                            <arg>-jar</arg>
                            <arg>maven/sample-model-1.0.0-SNAPSHOT.jar</arg>
                        </exec>
                    </entryPoint>           
                    <assembly>          
                        <descriptorRef>artifact-with-dependencies</descriptorRef>
                    </assembly>
                    <ports>
                        <port>8080</port>
                    </ports>
                </build>                        
            </image>            
        </images>
    </configuration>
    <executions>
        <execution>
            <id>docker-build</id>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>                       
</plugin>       

在 Spring boot maven 插件中添加了分类器配置作为集成测试模块的 exec,以识别要引导的 Spring boot 应用程序类。

在我的集成测试模块中,我使用故障安全插件进行集成测试。有关集成测试模块中的插件定义,请参见下文

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.18.1</version>
    <executions>
        <execution>
            <id>integration-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <includes>
                    <include>**/*.java</include>
                </includes>
                <groups>io.sample.test.IntegrationTest</groups>
                <skipTests>${skip.integration.tests}</skipTests>
            </configuration>
        </execution>
    </executions>
</plugin>

我的 IntegrationTest 类定义如下。

@RunWith(SpringRunner.class)
@Category(IntegrationTest.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class ControllerIT 
{
    @Autowired
    private MockMvc mockMvc;


    @Autowired
    private Environment env;



    @Test
    public void IntegrationTestForService() throws Exception {

        JsonNode node=mapper.readTree(new File("/src/integration-test/resources/Request.json"));
        RequestBuilder requestBuilder = MockMvcRequestBuilders
                .post("/api/sample/v1")
                .accept(MediaType.APPLICATION_JSON).content(node.toString())
                .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(requestBuilder).andReturn();

        MockHttpServletResponse response = result.getResponse();

        assertEquals(HttpStatus.CREATED.value(), response.getStatus());

    }
}

IntegrationTest 执行良好并且能够测试 REST API。但是,当我尝试使用 docker run 使用 module1 jar 文件运行 docker 文件时,spring boot 没有启动。它说未找到清单。下面是错误信息。

没有主清单属性,在 maven/sample-model-1.0.0-SNAPSHOT.jar 中。

当我从模块 1 中删除 exec 分类器时,spring boot 能够在执行 docker run 命令时启动。但是,如果分类器不存在,我在使用 Spring boot Test 执行集成测试用例时遇到问题。

您能否建议是否有任何选择。

标签: mavendockerspring-bootintegration-testing

解决方案


我认为如果您要使用分类器为 Spring Boot 生成一个单独的重新打包的 jar,那么您需要在 docker-maven-plugin 配置中引用该重新打包的 jar。也就是说,您<entrypoint><exec>应该调用 sample-model-1.0.0-SNAPSHOT-exec.jar。(注意“-exec”)

此外,为了良好的实践,您可能需要考虑为您的 jar 目标使用项目变量,而不是对版本进行硬编码,例如:

<entrypoint>
    <exec>
        <arg>java</arg>
        <arg>-jar</arg>
        <arg>maven/${project.artifactId}-${project.version}-exec.jar</arg>
    </exec>
</entrypoint>

您还需要将您的程序集从带有依赖关系的工件描述符引用更改为内联程序集,以便将 jar 的“exec”版本内置到您的 Docker 映像中。(另请注意,artifact-with-dependencies 将所有这些冗余依赖项扔到您的图像中,使其比需要的更大。)

<assembly>
  <inline>
    <fileSets>
      <fileSet>
        <directory>target</directory>
        <outputDirectory>.</outputDirectory>
        <fileMode>0644</fileMode>
        <includes>
          <include>${project.artifactId}-${project.version}-exec.jar</include>
        </includes>
      </fileSet>
    </fileSets>      
  </inline>
</assembly>

推荐阅读