Search code examples
javaspring-bootproduction-environmentdemoembedded-server

Spring Boot API Mocking In Production


I know, we can mock our code in test scope easily in Spring-Boot. In here, I want to try create a demo-production scope/profile in Spring Boot. And in this profile, I want to work with mock sceneries.

For example, In my code, there are third party API calls:

String API_URL = "https://external.com/v1/%s";
private CloseableHttpClient httpClient;
public Result executeRequest(String apiVersion, String subUrl, HttpMethod httpMethod)
{
    try
    {
        HttpRequestBase httpRequest;
        String url = String.format(API_URL, subUrl);
        if (httpMethod.equals(HttpMethod.GET))
        {
            httpRequest = new HttpGet(url);
        }
        else if (httpMethod.equals(HttpMethod.POST))
        {
            httpRequest = new HttpPost(url);
            ((HttpPost) httpRequest).setEntity(new StringEntity(requestBody, "UTF-8"));
        }
        ...
        headers.forEach(httpRequest::setHeader);
        HttpResponse response = httpClient.execute(httpRequest);
    }
    catch (IOException e)
    {
        logger.error("IO Error: {}", e.getMessage());
        return handleExceptions(e);
    }
} 

Is there a way to mock it in production? Or better way; is there a way to create embedded server for it like (wiremock)?

Note: I have already implemented different profile properties on my project like (production, test and dev) so this is not related with to use different profiles. In here, I just want to mock API in production not in test profile. And of course for demo profile, I will create demo.properties


Solution

  • Solution 1:

    It is possible to achieve the behavior with below configuration

    @Configuration
    @Profile("!demo")
    public class ProductionConfiguration {
    
        // Real configuration
    }
    
    
    @Configuration
    @Profile("demo")
    public class ProductionConfiguration {
    
        // Mock configuration
    }
    

    As @MockBean annotation is part of spring test dependency, it won't be available when your application is deployed. You need to create mocks on your own Type mockObj = Mockito.mock(Type.class)

    But this requires mockito dependency to be packaged as part of generated artifact.

    Solution 2: (Recommended)

    • Externalize the API URL to properties file.
    • Create a separate properties file application-demo.properties to be used for demo purpose
    • Update URLs in this properties file to connect to an external WireMock service

    This ensures that your production artifact doesn't need to contain unnecessary dependencies used only for demo purpose.

    If required, you may choose to spin-up an embedded WireMock server when demo profile is active. But that means related dependencies must either be part of your dependencies or be available in classpath. If possible it is better to run WireMock as an external service.

    Sample code for Solution 2 is available here for your reference.