【问题标题】:Integration testing Spring Boot based Microservices基于 Spring Boot 的微服务集成测试
【发布时间】:2015-06-24 15:18:22
【问题描述】:

我已经阅读了许多有关使用 Spring Boot 和 RESTful 服务的指南,其中许多包含有关运行单元测试的信息,其中最著名的是“使用 Spring Boot 构建应用程序”。但是,我还没有看到任何示例说明如何对使用/依赖于其他 Spring Boot 应用程序的 Spring Boot 应用程序进行单元测试,这在云微服务架构中很常见。因此,例如,我们有以下 Spring Boot 服务:

服务中介, 适配器1, 适配器2

ServiceMediator 调用 Adapter1 或 Adapter2,具体取决于输入。

有没有办法在 Spring JUnit 测试中启动和测试 ServiceMediator 之前启动 Spring Boot 服务 Adapter1 和 Adapter2?

【问题讨论】:

  • 您是在谈论单元测试来模拟 serviceMediator 的位置,还是要进行集成测试来确定调用真实服务的位置?
  • 我说的是集成测试。
  • 我想这真的取决于你如何定义它。我只是在寻找一种以自动化方式测试本地机器上所有服务的方法。因此,有没有办法在测试中介之前启动中介所依赖的服务?
  • 我找到了一种方法来做到这一点,但我不知道这是否是最好的方法。我愿意接受更好的方法,所以如果有人有更好的方法,请分享。在测试中介之前,我正在使用 ProcessBuilder 启动适配器。

标签: junit spring-boot microservices


【解决方案1】:
package controller;


import static org.junit.Assert.assertThat;

import java.io.File;
import java.net.URL;

import mediator.CLPApplication;

import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CLPApplication.class)
@WebAppConfiguration
@IntegrationTest()
public class ControllerTest {

    @Value("${adapter.dependency.jar.location}")
    private String adapterDependencyJarLocation;

    @Value("${adapter.dependency.jar.name}")
    private String adapterDependencyJarName;

    @Value("${adapter.url}")
    private String adapterURL;

    @Value("${mediator.url}")
    private String mediatorURL;

    private URL mediator;
    private URL adapter;
    private RestTemplate template;
    Process process = null;

    @Before
    public void setUp() throws Exception {

        adapter = new URL(adapterURL);
        template = new TestRestTemplate();

        //
        // Start the Atomic adapter
        // 
        System.out.println(adapterDependencyJarLocation);
        System.out.println("Starting Adapter");

        try {
            process = new ProcessBuilder("java", "-jar", adapterDependencyJarName)
                .directory(new File(adapterDependencyJarLocation)).start();

            // Try connecting 5 times with a 5 second pause between each
            // to see if it started. 
            Thread.sleep(5000);
            for(int i = 0; i <= 5; i++) {
                try{
                    System.out.println("Testing to see if Adapter is up");
                    template.getForEntity(adapter.toString(), String.class);
                    System.out.println("Adapter Started");
                    break;
                }
                catch(RestClientException rce){
                    System.out.println("It's not up yet");
                }
                Thread.sleep(5000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testMediator() throws Exception {
        mediator = new URL(mediatorURL);
        System.out.println("Calling Mediator");
        ResponseEntity<String> response = template.getForEntity(mediator.toString(), String.class);
        System.out.println(response.getBody());
        // Getting back JSON, so check to see if it starts with an open bracket
        assertThat(response.getBody(), Matchers.startsWith("{"));
    }

    @After
    public void tearDown() {
        if(process != null) {
            process.destroy();
        }
    }
}

【讨论】:

    【解决方案2】:

    process-exec-maven-plugin 可能会有所帮助,因为它允许在 pre-integration-test 阶段(作为标准 Spring Boot 应用程序)启动多个 java 进程,并在集成后测试阶段。

    注意:集成测试应该在 integration-test 阶段运行,因为 ma​​ven-failsafe-plugin 应该配置为spring-boot-maven-plugin see。 然后运行我们的集成测试 verify 或更高版本的 maven Lifecycle 应该是目标,因为 integration-test 阶段实际上位于 package 和 验证生命周期see Default Lifecycles

    以下 maven (pom.xml) 配置对我有用:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.3.5.RELEASE</version>
                <executions>                    
                    <execution>
                        <id>pre-integration-test</id>
                        <goals>
                            <goal>start</goal>
                        </goals>
                        <configuration>
                            <skip>${integration-tests.skip}</skip>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                        <configuration>
                            <skip>${integration-tests.skip}</skip>
                        </configuration>
                    </execution>
                </executions>
            </plugin>           
    
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <skip>${integration-tests.skip}</skip>                  
                    <includes>
                        <include>**/*IT.java</include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>                        
                    </execution>                    
                </executions>
            </plugin>
    
            <plugin>
                <groupId>com.bazaarvoice.maven.plugins</groupId>
                <artifactId>process-exec-maven-plugin</artifactId>
                <version>0.7</version>
                <executions>                    
                    <execution>
                        <id>switchboard-process</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                        <configuration>
                            <name>accounts-service</name>
                            <workingDir>/../../micro-service</workingDir>
                            <waitForInterrupt>false</waitForInterrupt>                          
                            <arguments>
                                <argument>java</argument>
                                <argument>-jar</argument>
                                <argument>${basedir}/../micro-service/target/micro-service-${project.version}-exec.jar</argument>
                            </arguments>
                        </configuration>
                    </execution>
                    <!--Stop all processes in reverse order-->
                    <execution>
                        <id>stop-all</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop-all</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    test.java 文件夹中有一个集成测试类 (WebServerIT):

    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = WebServerApp.class)
    @WebIntegrationTest("server.port:0")
    public class WebServerIT {
    
        @Autowired
        private WebApplicationContext webServerAppContext;
    
        private MockMvc webServerMockMvc;
    
        @Before
        public void setUp() {
            System.out.println("the test is set up");
            webServerMockMvc = MockMvcBuilders.webAppContextSetup(webServerAppContext).build();
        }
    
        /**
         * This test calls the WebServer's endpoint (/accounts/123456789) which in turn calls the micro-service rest api 
         * which is started using the process-exec-maven-plugin, otherwise the test would fail.
         */
        @Test
        public void testWebServerInteractionWithMicroService() throws Exception {
            this.webServerMockMvc.perform(get("/accounts/123456789"))
                    .andExpect(status().isOk());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-23
      • 2015-08-02
      • 2015-03-22
      • 2012-02-25
      • 2021-02-08
      • 1970-01-01
      • 2018-06-28
      • 2020-02-25
      相关资源
      最近更新 更多