【问题标题】:How to use Spring profiles to mock different services that implement the same interface如何使用 Spring 配置文件来模拟实现相同接口的不同服务
【发布时间】:2019-08-23 05:10:49
【问题描述】:

我有以下场景:

我有一个 Springboot 微服务,它可以收集来自不同提供商的产品列表(外部 SOAP Web 服务)。我们目前从 2 家提供商那里获取信息,例如亚马逊和 EBay。

但将来我可以拥有更多的提供者,所以我的应用程序需要可扩展。

此外,我可以从 Amazon 或 Ebay 收集信息,也可以从这两种服务中获取信息,如果提供商列表增加,例如,我可以添加 AliExpress,我应该能够选择 Amazon + AliExpress 或Ebay + AliExpress 或三个。

我创建了一个界面:

public interface ProductsService {
   List<Product> getProducts();
}

以及实现这个接口的类:

public class AmazonProductsService implements ProductService {
   public List<Product> getProducts() {
      // Logic to call SOAP Web Service for Amazon Products
   }
}

public class EbayProductsService implements ProductService {
   public List<Product> getProducts() {
      // Logic to call SOAP Web Service for Ebay Products
   }
}

到目前为止,我设法让它们工作,我还有一些适配器类,它们从服务中获取信息并将它们调整为我定义的 POJO。

问题出现是因为我需要提供一种机制来模拟每个不同的服务。我的意思是,我需要为 Amazon、Ebay 以及我的 Springboot 应用程序需要联系的每个提供商提供一个模拟。

在另一个项目中,我使用了很有用的 Spring Profiles,因为我能够定义一个“模拟”配置文件,但在这种情况下,我只有一个服务,在这种情况下,我有许多服务实现了相同的接口。

到目前为止,我尝试的是:

public class MockAmazonProductsService implements ProductsService {
   public List<Product> getProducts() {
      return new ArrayList<Product>();
   }
}

我也创建了它的配置:

@Configuration
@Profile("mockamazon")
public class MockAmazonProductsServiceAutoconfiguration {
   @Bean
   public ProductsService amazonProductsService() {
      return new MockAmazonProductsService();
   }
}

我为 Ebay 服务做了同样的事情(配置文件是“mockebay”)。

我的问题是,设置配置文件后如何调用模拟服务,例如:

spring.profiles.active=mockamazon

在模拟的要求之前,我有以下课程:

@Service
public class ProductsServiceFactory {
   @Autowired
   @Qualifier("AmazonProductsService")
   private ProductsService amazonProductsService;

   @Autowired
   @Qualifier("EbayProductsService")
   private ProductsService ebayProductsService;

   public List<ProductsService> getProductsService(String selectedServicesParameter) {
      String[] selectedServices = selectedServicesParameter.split(",");        
      List<ProductsService> servicesList = new ArrayList<>();

      for (String selectedService : selectedServices) {
          if (selectedService.equals("AMAZON") {
             servicesList.add(amazonProductsService);
          } else if (selectedService.equals("EBAY") {
             servicesList.add(ebayProductsService);
          }
      }
      return servicesList;
   }
}

但是现在,我不确定如何调用模拟服务。我曾想过为模拟服务创建一个额外的服务工厂,但我可能会遇到只需要模拟一个服务而不是所有服务的场景。

任何建议都将受到高度赞赏。

【问题讨论】:

    标签: java spring spring-boot mocking spring-profiles


    【解决方案1】:

    我不能说我的解决方案是完美的,但它确实有效。

    您可以为每个案例创建配置文件并像这样进行配置:

    @Configuration
    public class MockServiceAutoconfiguration {
    
       @Profile({"mockAmazon", "mockAll", "mockAmazonAndEbay"})
       @Bean
       public ProductsService amazonProductsService() {
          return new MockAmazonProductsService();
       }
    
       @Profile({"mockAliexpress", "mockAll"})
       @Bean
       public ProductsService aliexpressProductsService() {
          return new MockAliexpressProductsService();
       }
    
    }
    

    【讨论】:

    • 感谢您的回答,让我试一试,到目前为止,我知道我应该为我的“官方”服务提供商创建一个 ProductServiceAutoconfiguration ,对吗?并且该配置不应使用配置文件,而应仅使用“bean”。在这种情况下应该如何调用?
    • 经过一段时间的努力,我会将答案标记为已接受的解决方案。在迁移到不同的内部构建框架后,团队设法实现了我们想要的。非常感谢!
    猜你喜欢
    • 2021-09-03
    • 2011-02-09
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    相关资源
    最近更新 更多