Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Tuesday, November 19, 2019

Better integration tests with WireMock

No matter if you follow the classical test pyramid or one of the newer approaches like the Testing Honeycomb you should start writing integration tests at some point during development.
There are different types of integration tests you can write. Starting with persistence tests, you can check the interaction between your components or you can simulate calling external services. This article will be about the latter case.
Let us start with a motivating example before talking about WireMock.

The ChuckNorrisFact service

The complete example can be found on GitHub.
You might have seen me using the Chuck Norris fact API in a previous blog post. The API will serve us as an example for another service that our implementation depends on.
We have a simple ChuckNorrisFactController as the API for manual testing. Next to the “business” classes there is the ChuckNorrisService that does the call to the external API. It uses Spring’s RestTemplate. Nothing special.
What I have seen many times are tests that mock the RestTemplate and return some pre-canned answer. The implementation could look like this:
@Service
public class ChuckNorrisService{
...
  public ChuckNorrisFact retrieveFact() {
    ResponseEntity<ChuckNorrisFactResponse> response = restTemplate.getForEntity(url, ChuckNorrisFactResponse.class);
    return Optional.ofNullable(response.getBody()).map(ChuckNorrisFactResponse::getFact).orElse(BACKUP_FACT);
  }
 ...
 }
Next to the usual unit tests checking for the success cases there would be at least one test covering the error case, i.e. a 4xx or 5xx status code:
  @Test
  public void shouldReturnBackupFactInCaseOfError() {
    String url = "http://localhost:8080";
    RestTemplate mockTemplate = mock(RestTemplate.class);
    ResponseEntity<ChuckNorrisFactResponse> responseEntity = new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE);
    when(mockTemplate.getForEntity(url, ChuckNorrisFactResponse.class)).thenReturn(responseEntity);
    var service = new ChuckNorrisService(mockTemplate, url);

    ChuckNorrisFact retrieved = service.retrieveFact();

    assertThat(retrieved).isEqualTo(ChuckNorrisService.BACKUP_FACT);
  }
Doesn’t look bad, right? The response entity returns a 503 error code and our service will not crash. All tests are green and we can deploy our application.
Unfortunately, Spring’s RestTemplate does not work like this. The method signature of getForEntity gives us a very small hint. It states throws RestClientException. And this is where the mocked RestTemplate differs from the actual implementation. We will never receive a ResponseEntity with a 4xx or 5xx status code. The RestTemplate will throw a subclass of RestClientException. Looking at the class hierarchy we can get a good impression of what could be thrown:
Therefore, lets see how we can make this test better.

WireMock to the rescue

WireMock simulates web services by starting a mock server and returning answers you configured it to return. It is easy to integrate into your tests and mocking requests is also simple thanks to a nice DSL.
For JUnit 4 there is a WireMockRule that helps with starting an stopping the server. For JUnit 5 you will have to do it yourself. When you check the example project you can find the ChuckNorrisServiceIntegrationTest. It is a SpringBoot test based on JUnit 4. Let’s take a look at it.
The most important part is the ClassRule:
  @ClassRule
  public static WireMockRule wireMockRule = new WireMockRule();
As mentioned before, this will start and stop the WireMock server. You could also use the rule as normal Rule to start and stop the server for each test. For our test this isn’t necessary.
Next, you can see several configureWireMockFor... methods. These contain the instructions for WireMock when to return what answer. Splitting the WireMock configuration into several methods and calling them from the tests is my approach to using WireMock. Of course you could set up all possbile requests in an @Before method. For the success case we do:
  public void configureWireMockForOkResponse(ChuckNorrisFact fact) throws JsonProcessingException {
    ChuckNorrisFactResponse chuckNorrisFactResponse = new ChuckNorrisFactResponse("success", fact);
    stubFor(get(urlEqualTo("/jokes/random"))
        .willReturn(okJson(OBJECT_MAPPER.writeValueAsString(chuckNorrisFactResponse))));
  }
All methods are imported statically from com.github.tomakehurst.wiremock.client.WireMock. As you can see, we stub an HTTP GET to a path /jokes/random and return a JSON object. The okJson() method is just shorthand for a 200 response with JSON content. For the error case the code is even more simple:
  private void configureWireMockForErrorResponse() {
    stubFor(get(urlEqualTo("/jokes/random"))
        .willReturn(serverError()));
  }
As you can see, the DSL makes it easy to read the instructions.
Having WireMock in place we can see that our previous implementation does not work since the RestTemplate throws an exception. Therefore, we gotta adjust our code:
  public ChuckNorrisFact retrieveFact() {
    try {
      ResponseEntity<ChuckNorrisFactResponse> response = restTemplate.getForEntity(url, ChuckNorrisFactResponse.class);
      return Optional.ofNullable(response.getBody()).map(ChuckNorrisFactResponse::getFact).orElse(BACKUP_FACT);
    } catch (HttpStatusCodeException e){
      return BACKUP_FACT;
    }
  }
This already covers WireMock’s basic use-cases. Configure an answer for a request, execute the test, check the results. It’s as simple as that.
Still, there is one problem you will usually encounter when you run your tests in a cloud environment. Let’s see what we can do.

WireMock on a dynamic port

You might have noticed that the integration test in the project contains an ApplicationContextInitializer class and that its @TestPropertySource annotation overwrites the URL of the actual API. That is because I wanted to start WireMock on a random port. Of course you can configure a fixed port for WireMock and use this one as hard-coded value in your tests. But if your tests are running on some cloud providers infrastructure you cannot be sure that the port is free. Therefore, I think a random port is better.
Still, when using properties in a Spring application we have to pass the random port somehow to our service. Or, as you can see in the example, overwrite the URL. That is why we use the ApplicationContextInitializer. We add the dynamically assigned port to the application context and then we can refer to it by using the property ${wiremock.port}. The only disadvantage here is that we now have to use a ClassRule. Else, we couldn’t access the port before the Spring application is being initialized.
Having solved this problem, let’s take a look at one common problem when it comes to HTTP calls.

Timeouts

WireMock offers many more possibilities for responses than just simple answers to GET requests. Another test case that is often forgotten is testing timeouts. Developers tend to forget to set timeouts on the RestTemplate or even on URLConnections. Without timeouts both will wait for an infinite amount of time for responses. In the best case you will not notice, in the worst case all your threads wait for a response that will never arrive.
Therefore, we should add a test that simulates a timeout. Of course, we can also create a delay with e.g. a Mockito mock, but in that case we would guess again how the RestTemplate behaves. Simulating a delay with WireMock is pretty easy:
  private void configureWireMockForSlowResponse() throws JsonProcessingException {
    ChuckNorrisFactResponse chuckNorrisFactResponse = new ChuckNorrisFactResponse("success", new ChuckNorrisFact(1L, ""));
    stubFor(get(urlEqualTo("/jokes/random"))
        .willReturn(
            okJson(OBJECT_MAPPER.writeValueAsString(chuckNorrisFactResponse))
                .withFixedDelay((int) Duration.ofSeconds(10L).toMillis())));
  }
withFixedDelay() expects an int value representing milliseconds. I prefer using Duration or at least a constant that indicates that the parameter represents milliseconds without having to read the JavaDoc every time.
After setting a timeout on our RestTemplate and adding the test for the slow response we can see that the RestTemplate throws a ResourceAccessException. So we can either adjust the catch block to catch this exception and the HttpStatusCodeException or just catch the superclass of both:
  public ChuckNorrisFact retrieveFact() {
    try {
      ResponseEntity<ChuckNorrisFactResponse> response = restTemplate.getForEntity(url, ChuckNorrisFactResponse.class);
      return Optional.ofNullable(response.getBody()).map(ChuckNorrisFactResponse::getFact).orElse(BACKUP_FACT);
    } catch (RestClientException e){
      return BACKUP_FACT;
    }
  }
Now we have nicely covered the most common cases when doing HTTP requests and we can be sure that we are testing close to real world conditions.

Why not Hoverfly?

Another choice for HTTP integration tests is Hoverfly. It works similar to WireMock but I have come to prefer the latter. The reason is that WireMock is also quite useful when running end-to-end tests that include a browser. Hoverfly (at least the Java library) is limited by using JVM proxies. This might make it faster than WireMock but when e.g. some JavaScript code comes into play it does not work at all. The fact that WireMock starts a webserver is very useful when your browser code also calls some other services directly. You can then mock those with WireMock, too, and write e.g. your Selenium tests.

Conclusion

I hope this article could show you two things:
  1. the importance of integration tests
  2. that WireMock is pretty nice
Of course, both topics could fill many more articles. Still, I wanted to give you a feeling of how to use WireMock and what it is capable of. Feel free to check their documentation and try many more things. As an example, testing authentication with WireMock is also possible.

Wednesday, February 24, 2016

Extension/Service/Plugin mechanisms in Java

Since I started to deep dive into OSGi I was wondering more and more how frameworks that have some way of extension mechanism, e.g. Apache Camel where you can define your own endpoint or the Eclipse IDE with its plugins, handle finding and instantiating extensions. I remember very well a presentation from the JAX 2013, it was by Kai Tödter, where he showed the combination of Vaadin and OSGi. While the web app was running he could add and remove menu entries, just by starting and stopping the bundles.
For a while now I have taken a look at several approaches on how to create an extensible application and you can find resources for every single method. I want to give a medium sized (not short ;)) overview here of the different ways I know to make a Java application extensible. Also, I will add a list of advantages and disadvantages, from my point of view, to each method. For every method I try to give a simple example.
To avoid confusion, when I write about the advantages and disadvantages, I will write from the point of view, as if you want to provide this extension mechanism in your framework, not from the API consumer point of view.

Passing the object

This is the most obvious method. The framework defines a method which takes the SPI interface and you simply pass the object. Camel, next to other methods, makes use of this (example taken from the Camel FAQ):
CamelContext context = new DefaultCamelContext();
context.addComponent("foo", new FooComponent(context));
Internally, Camel doesn't do much magic (code taken from Camel on GitHub).
public void addComponent(String componentName, final Component component) {
    ObjectHelper.notNull(component, "component");
    synchronized (components) {
        if (components.containsKey(componentName)) {
            throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
        }
        component.setCamelContext(this);
        components.put(componentName, component);
        for (LifecycleStrategy strategy : lifecycleStrategies) {
            strategy.onComponentAdd(componentName, component);
        }

        // keep reference to properties component up to date
        if (component instanceof PropertiesComponent && "properties".equals(componentName)) {
            propertiesComponent = (PropertiesComponent) component;
        }
    }
}
Every component has to have an unique name and is somehow bound to a lifecycle. Removal of a component is also possible, but has to be made somewhere from the user code.

Advantages

  • Easy and straightforward
  • No need for an additional framework
  • Compiler checks for the correct interface

Disadvantages

  • Access to central class (the plugin/service/component holder) is necessary
  • Allowing changes during the runtime is possible but complicated, since it has to be assured the component is removed everywhere
  • Your framework has to take care of the whole component lifecycle and any additional requirements it enforces

Interface and Reflection

This method is used quite often (basically it is also how the ServiceLoader works, see next section) and you can find it with small variances. The differences are where and how exactly interface and implementation name reach the application. Placing them somewhere inside a properties file or passing them to the framework during startup are most common. The implementation is then instantiated using reflection. Creating a context with an InitialContextFactory works like this e.g.:
  Properties env = new Properties();
  env.put(Context.INITIAL_CONTEXT_FACTORY,
          "org.jboss.naming.remote.client.InitialContextFactory");

Advantages

  • Easy and straightforward
  • No need for an additional framework
  • No need to provide central class (in properties file approach)

Disadvantages

  • No type safety (if text based)
  • Your framework has to take care of the whole lifecycle and any additional requirements it enforces
  • Check for correct wiring only during runtime (if text based, check either at startup or when the code is being called, where the former is better than the latter)

java.util.ServiceLoader

Frameworks using the java.util.ServiceLoader can also be found quite often. What the ServiceLoader does is, it uses during runtime a ClassLoader and checks the META-INF/services directory for a text file, whose name equals the passed interface (SPI) name and then reads the class name inside that file. Then it instantiates the class via Reflection. All the magic happens in the LazyIterator inside the ServiceLoader class (see OpenJDK). Basically, it's just reading a file and instantiating the object. E.g. Camel and HiveMQ use this method.

Advantages

  • Easy and straightforward
  • ServiceLoader is part of JDK
  • No need for an additional framework

Disadvantages

  • No lifecycle
  • Class has to provide standard constructor
  • Support for runtime changes must be implemented (as mentioned here)
  • Check for correct wiring only during runtime (the filename or the string inside the file could be wrong)

(Eclipse) Extension Points

Picture under BSD license, see here
As far as I know the concept of Extension Points never got popular outside Eclipse, although it is possible to include them in every application. To achieve loose coupling the definition of places where you can add your plugin and the plugins themselves is extracted into XML files.
To define an extension point you need something like this:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
   <extension-point
     id="de.blogspot.wrongtracks.FooService"
     name="FooService"
     schema="schema/de.blogspot.wrongtracks.FooService.exsd"/>
The extension provider then has to define an appropriate extension for that point:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="de.blogspot.wrongtracks.FooService">
      <implementation
            class="com.example.impl.FooServiceImpl"
            id="com.example.impl.FooServiceImpl"
            name="FooServiceImpl">
      </implementation>
   </extension>
</plugin>
I got to admit, that I am not completely sure how exactly you can integrate the extension points, but I guess you will need quite a lot from the basic Eclipse runtime. There is a blog post, which explains how you can use extension points without depending on OSGi.

Advantages

  • Extensions can be added during runtime
  • Good tool support inside Eclipse
  • Wrong wiring only affects single extension
  • Loose coupling (more or less, since the extensions depend on the extension point id)

Disadvantages

  • Dependencies to Eclipse
  • Overhead from the Eclipse platform (I actually cannot prove this point but I assume there must be a considerate overhead involved in comparison to the previous methods)
  • Check for correct wiring only during runtime

Spring XML

The Spring framework tried to find a way for loosely coupled components long before CDI, as we know it today, appeared. Their solution was an XML file in which the different classes are being wired together (I am well aware of the fact that nowadays there are also other ways, but since they are also based on annotations they don't differ enough from CDI as that I'll give them an own paragraph). In the basic XML file you define all your beans and Spring will take care of the instantiation. It is also possible to distribute the configuration among several XML files. A very simple example (taken and modified from the Spring documentation) looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
    </bean>

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
    </bean>
</beans>
If you want to provide your users a way to add their services/plugins to the framework, you'll have to provide a setter method where the users can add their object. E.g. like this (taken from camunda documentation):
<bean id="processEngineConfiguration" class="org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration">
  ...
  <property name="processEnginePlugins">
    <list>
      <bean id="spinPlugin" class="org.camunda.spin.plugin.impl.SpinProcessEnginePlugin" />
    </list>
  </property>
</bean>

Advantages

  • Spring is lightweigth
  • Lifecycle support from Spring

Disadvantages

  • XML needs to be maintained
  • No auto detection, users have to write the XML when they want to add something
  • The Spring IoC container is needed
  • Correct wiring is only checked at startup

OSGi Services

OSGi was created embracing runtime changes and bundles dynamically providing and removing their services. With this in mind OSGi strongly supports applications being extended by services, provided by different bundles. The simplest approach is to implement a ServiceListener or a ServiceTracker. Both should be created on bundle start and they will react when a new implementation of the service appears. A ServiceListener can be as simple as this (taken from the Knoplerfish tutorial):
 ServiceListener sl = new ServiceListener() {
   public void serviceChanged(ServiceEvent ev) {
      ServiceReference sr = ev.getServiceReference();
      switch(ev.getType()) {
        case ServiceEvent.REGISTERED:
          {
             HttpService http = (HttpService)bc.getService(sr);
             http.registerServlet(...);
          }
          break;
        default:
          break;
      }
   }
 };

 String filter = "(objectclass=" + HttpService.class.getName() + ")";
 bc.addServiceListener(sl, filter);
Where bc is a BundleContext object. And a ServiceTracker can be used like this:
ServiceTracker<HttpService,HttpService> serviceTracker = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null);
serviceTracker.open();
There are more elegant ways to get hold of an OSGi service using Blueprint, Declarative Services or the Apache Felix Dependency Manager but the ServiceListener is the basic way.

Advantages

  • OSGi lifecycle support
  • Changes during runtime "encouraged" ;)
  • Compiler checks wiring (not for the ServiceListener but for the rest)
  • Problems with services are restricted to single bundle

Disadvantages

  • You have to buy the whole OSGi package: imports, exports, bundles and everything
  • Having the full OSGi lifecycle makes the world more complicated since every service can disappear at every moment

Note about PojoSR/OSGi Light

Since the biggest disadvantage of OSGi is that you have to get the whole package, I want to mention here another approach, which is called PojoSR or OSGi Light. The goal of it is to give you the OSGi service concept without the rest that comes with OSGi. Unfortunately, I could not find much documentation about it and the activity around this project seems to be very low at the moment. There is an article here and the PojoSR framework itself. Also, it looks like PojoSR is now a part of Apache Felix called "Connect", but its version is 0.1.0. So if anyone of you knows more about it, please let me know.

CDI

Contexts and Dependency injection was a big step for Java EE, allowing developers to write more loosely coupled code. The CDI container takes care of automagically wiring the different parts together. The developer only has to use the correct annotations. Depending on which CDI beans are present at runtime, concrete implementations can be changed without changing the code that uses them. When trying to use a class the basic injection looks like this:
@Inject
private MyServiceInterface service;
If there is need to get all of the implementations (which we actually want here), then the class Instance must be used:
@Inject @Any
private Instance<MyServiceInterface> services;
Since Instance is an Iterable a simple for-each loop can be used to access all the objects. Alternatively the select() method can be used to further specify requirements.

Advantages

  • Compiler checks for correct type
  • CDI container checks correct wiring at startup
  • Part of JEE standard but can also be used without application serve (use a JSR-330 implementation like Guice or HK2)r
  • CDI lifecycle support

Disadvantages

  • A CDI container is needed
  • Changes during runtime are not possible
  • Annotatiomania (at least if you don't watch out)

Summary

As you can see many different frameworks/methods evolved in the Java ecosystem. Every single one with its specific advantages and disadvantages. I think we can summarize the different extension mechanisms as three types (with their members):
  1. String and well-known location ("Interface and Reflection", "ServiceLoader", "(Eclipse) Extension Points", "Spring XML")
  2. Programmatic wiring ("Passing the object", "Interface and Reflection", "OSGi Services")
  3. Classpath scanning ("CDI")
Of course the three types are not exclusive. You may provide your users more than one way and let them choose. Also CDI is not exactly the only framework that uses classpath scanning. Spring with its two other ways for configuring the IoC container relies on that method, too.

I hope this article provides an good and sufficient overview of the different methods on how to create an extensible framework. Choosing the right one will make your users surely happy. If you know another method, which I forgot, please let me know, I will gladly add it here.

Please note that the lists of advantages and disadvantages are based on my reasoning. I tried to be objective but like every programmer I have my favorites and my experiences with the frameworks that may make me a little bit biased.

 

Copyright @ 2013 Wrong tracks of a developer.

Designed by Templateiy