如何使用 Spring 配置文件模拟实现相同接口的不同服务

How to use Spring profiles to mock different services that implement the same interface

我有以下场景:

我有一个 Springboot 微服务,它可以收集来自不同提供商(外部 SOAP 网络服务)的产品列表。我们目前从 2 个供应商处获取信息,例如 Amazon 和 EBay。

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

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

我创建了一个接口:

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

以及实现此接口的classes:

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
   }
}

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

问题来了,因为我需要提供一种机制来模拟每个不同的服务。我的意思是,我需要为亚马逊、Ebay 和我的 Spring 启动应用程序需要联系的每个供应商创建一个模拟。

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

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

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

在模拟的要求之前我有以下 class:

@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;
   }
}

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

如有任何建议,我们将不胜感激。

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

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

@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();
   }

}