【问题标题】:Start MockServer during spring-boot:run在 spring-boot:run 期间启动 MockServer
【发布时间】:2021-08-28 17:22:16
【问题描述】:

由于防火墙,我们在应用程序中使用的一些 API 无法从本地开发人员机器访问。

我想使用 mockServer 来模拟其中的一些 API,以便我们可以在本地开发。

在运行测试时,可以分别使用 maven 构建阶段 process-test-classesverify 启动和停止 mockServer。

当我使用mvn spring-boot:run 启动应用程序时,如何让它运行?

【问题讨论】:

    标签: java spring-boot maven mockserver


    【解决方案1】:

    在运行测试时,可以使用 maven 构建阶段 process-test-classes 和 verify 分别启动和停止 mockServer。

    因此必须有一些(pom)配置,例如:

    <plugin>
      <groupId>org.mock-server</groupId>
      <artifactId>mockserver-maven-plugin</artifactId>
      <version>3.10.8</version>
      <configuration>
        <serverPort>1080</serverPort>
        <proxyPort>1090</proxyPort>
        <logLevel>DEBUG</logLevel>
        <initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
      </configuration>
      <executions>
          <execution>
            <id>process-test-classes</id>
            <phase>process-test-classes</phase>
            <goals>
                <goal>start</goal>
            </goals>
          </execution>
          <execution>
            <id>verify</id>
            <phase>verify</phase>
            <goals>
                <goal>stop</goal>
            </goals>
          </execution>
      </executions>
    </plugin>
    

    这将在process-test-classes(所以在test 阶段之前)和stopvalidate(所以在(post-integration-test 阶段之后)启动一个模拟服务器。 (link1, link2)

    当我使用 mvn spring-boot:run 启动应用程序时,如何让它运行?

    使用mvn spring-boot:run 运行它:

    1. 只需运行mvn mockserver:start spring-boot:run! (将其打包到脚本/IDE 启动中..)(推荐
    2. 实现自定义插件,结合 spring-boot-maven 和 mockserver-maven-plugin...(然后运行 ​​mvn com.example:custom-plugin:run

    .

    【讨论】:

      【解决方案2】:

      我曾经为我的团队创建了一个 MockServer,用于非常相似的目的here(幸运的是,也可以使用简短的demo)。您可以独立设置此服务器(例如在本地主机上)并将请求(url 和有效负载)与您想要的相应响应 json 添加到此服务器。

      您需要在项目中进行的一次更改是在开发/测试期间将所有 API 请求路由到此 Mockserver,这可以通过更改您将使用的所有 API 的基本 URL 并设置具有适当 json 请求和响应的模拟服务器。它可以像这样简单地完成:

      public class BaseUrlLoader {
      
          public static String NEWSRIVER_BASE_URL;
          public static String FACEBOOK_BASE_URL;
          public static String TWITTER_BASE_URL;
      
          private static final String MOCKSERVER_BASE_URL = "mocksrvr.herokuapp.com/TEAM-SECRET-KEY";
      
          public static void load(){
              Properties properties= new Properties();
              String activeProfile;
              try{
                  properties.load(ClassLoader.getSystemResourceAsStream("application.properties"));
              } catch (IOException e) {
                  System.out.println("Not able to load the application.properties file");
                  return;
              }
              activeProfile = properties.getProperty("spring.profiles.active");
              System.out.println("Using "+activeProfile);
              if(activeProfile.equals("Test")){
                  NEWSRIVER_BASE_URL=MOCKSERVER_BASE_URL;
                  FACEBOOK_BASE_URL= MOCKSERVER_BASE_URL;
                  TWITTER_BASE_URL= MOCKSERVER_BASE_URL;
              }else{
                  NEWSRIVER_BASE_URL="api.newsriver.io";
                  FACEBOOK_BASE_URL="api.facebook.com";
                  TWITTER_BASE_URL="api.twitter.com";
              }
              System.out.println(NEWSRIVER_BASE_URL);
          }
      
      }
      
      
      // Example- Use APIs as
      public class NewsFetch {
          
          ...
          
          public NewsFetch(){ BaseUrlLoader.load(); }
          
          private URI buildURL(APIQuery apiQuery) throws URISyntaxException {
              String mainURL = BaseUrlLoader.NEWSRIVER_BASE_URL+"v2/search";
              URIBuilder url = new URIBuilder(mainURL);
              url.addParameter("query", apiQuery.getLuceneQuery());
              url.addParameter("soryBy", apiQuery.getSortBy());
              url.addParameter("sortOrder", apiQuery.getSortOrder());
              url.addParameter("limit", apiQuery.getLimit());
              return url.build();
          }
      
          public HttpResponse <String> fetch(APIQuery apiQuery) throws URISyntaxException, IOException, InterruptedException {
              URI uri = buildURL(apiQuery);
              HttpRequest request = HttpRequest.newBuilder()
                      .GET()
                      .header("Authorization", KEY)
                      .uri(uri)
                      .build();
              ...
      
          }
      }
      // and add the request like http://mocksrvr.herokuapp.com/TEAM-SECRET-KEY/v2/search/... to the Mockserver with the response you want.
      
      

      baseurl 将根据当前活动的配置文件而改变。这个模拟服务器很简单,甚至可以与 Slackbot 集成。在自述文件中查看更多信息。项目中可能存在许多错误,我们将不胜感激。

      【讨论】:

        【解决方案3】:

        可以在 springboot 上覆盖 bean。 因此,您可以根据需要使用 bean 并切换模拟值 下面的示例是覆盖服务并根据您的喜好使用模拟,但您也可以使用接口。

        创建服务

        @Service
        public class ServiceReal {
        
            @Autowired(required = false) // must be required=false. May be disabled by using mock configuration
            private JdbcTemplate jdbcTemplate;
        
            public String getInfo() {
                return  jdbcTemplate...// get a real value from database
            }
        
        }
        

        创建模拟服务

        
        @Service
        @Primary
        @Profile("mocklocal")
        public class ServiceMock extend ServiceReal {
        
            @Override
            public String getInfo() {
                return  "Mocked value"
            }
        }
        
        

        配置 bean 以便稍后在属性上选择其中之一

        @Profile("mocklocal")
        @PropertySource("classpath:application-mocklocal.properties")
        @Configuration
        public class ConfigMock {
        
            private static final String  PROP_VALUE_TRUE = "true";
            private static final boolean PROP_FALSE_DEFAULT_MISSING = false;
            private static final String  PROP_SERVICE_REAL = "mocklocal.service.real";
            private static final String  PROP_SERVICE2_REAL = "mocklocal.service2.real";
            
            @Bean
            @ConditionalOnProperty( value = PROP_SERVICE_REAL, havingValue = PROP_VALUE_TRUE, matchIfMissing = PROP_FALSE_DEFAULT_MISSING)
            public ServiceReal serviceReal(){
                return new ServiceMock();
            }
            
            @Bean
            @ConditionalOnProperty( value = PROP_SERVICE2_REAL, havingValue = PROP_VALUE_TRUE, matchIfMissing = PROP_FALSE_DEFAULT_MISSING)
            public Service2Real service2Real(){
                return new Service2Mock();
            }   
        }
        

        配置您的 application-mocklocal.properties 以使用模拟

        # using ConfigMock
        spring.profiles.active=mocklocal
        
        # settig spring to override service and use mock
        spring.main.allow-bean-definition-overriding=true
        
        # disable some configuration not required in mocks. you can adjust for amqp, database or other configuration
        spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
        spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
        spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.orm.jpa.DataSourceTransactionManagerAutoConfiguration
        
        # enable your service to use mocks not real services
        mocklocal.service.real=true
        mocklocal.service2.real=true
        

        因此,如果您使用 --spring.profiles.active=mocklocal 启动应用程序,您将获得模拟值

        你也可以在测试中使用

        @ExtendWith(SpringExtension.class)
        @AutoConfigureMockMvc
        @SpringBootTest
        @TestPropertySource(locations = "classpath:application-mocklocal.properties")
        public class RunIntegrationTests {
        
            @Autowired
            private MockMvc mockMvc;
            
            @Test
            public void run() throws Exception{
                ...
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-28
          • 1970-01-01
          • 2018-04-20
          • 1970-01-01
          • 1970-01-01
          • 2017-11-27
          • 1970-01-01
          • 2015-06-21
          相关资源
          最近更新 更多