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

Marcelo Tataje :

I have the following scenario:

I have a Springboot microservice that can gather a list of products from different providers (external SOAP web services). We currently get the information from 2 providers, for instance Amazon and EBay.

But in the future I can have more providers, so my application needs to be scalable.

Additionally, I can gather the information either from Amazon or Ebay as well as get the information from both services and if the list of providers increase, for instance, I can add AliExpress and I should be able to pick Amazon + AliExpress or Ebay + AliExpress or the three of them.

I created an interface:

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

As well as the classes that implement this interface:

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

So far, I managed to make them work, I have also some adapter classes that get the information from the services and adapt them to a POJO I defined.

The problem comes because I need to provide a mechanism to mock each of the different services. I mean, I need to have a mock for Amazon, for Ebay and for each provider my Springboot application would need to contact.

In another project I used Spring Profiles which was useful, because I was able to define a "mock" profile, but in that case I have only one service, in this case I have many of them implementing the same interface.

So far, what I tried was:

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

I created its configuration as well:

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

I did the same for the Ebay service (profile is "mockebay").

My question is, how can I can call the mock services when the profiles are set, for example:

spring.profiles.active=mockamazon

Before the requirement of the mock I had the following 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;
   }
}

But now, I am not sure how can I call the mock services. I thought of creating an additional Service Factory for mock services, but I can be in an scenario in which I would need to mock only one service and not all of them.

Any suggestion would be highly appreciated.

Roman Shevchenko :

I can't say that my solution is perfect but it works.

You can create profiles for each of your cases and make config like that:

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

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=154189&siteId=1