Blog post featured image

Even implementing a simple stateless micro-service, one could face situations where testing becomes hard. A lot of tools and techniques could help, but having something at hand quickly is very handy. In this post, I’m introducing a Quarkus feature that plays nice with Camel in order to mock beans for test purpose.

Camel and Quarkus together for mocking beans

It’s long known that Camel offers great support for Java beans. Every time a developer needs custom code, this feature comes to the rescue.

A route using a bean

Let’s take a simple route below for demonstration purpose:

from("platform-http:/semester").
choice().
  when(simple("${bean:monthBean} <= 6")).
  setBody(constant("FIRST semester")).
otherwise().
  setBody(constant("SECOND semester")).
end();

This simple Camel route informs the web client about the current semester. Step by step, it reacts to an incoming HTTP request, invokes a select method on a bean named monthBean, compares the returned value against the number 6 and finally set the reply accordingly. For instance, the HTTP response body will be FIRST semester when executed from January until June.

A bean used from a route

Now let’s define the bean invoked from the route with the code beneath:

@ApplicationScoped
@Named("monthBean")
@RegisterForReflection
public class MonthBean {
  public int month() {
    return LocalDateTime.now().getMonth().getValue();
  }
}

Helped with the @Named CDI annotation, we have just defined a bean named monthBean that could be referenced from a route. The month() method will return values ranging from 1 when executed in January up to 12 when executed in December.

A first canvas for testing

As we are creating a simple HTTP based service, we could leverage on the @QuarkusTest annotation and the RestAssured.given() method for testing purpose. A possible implementation is proposed underneath:

@QuarkusTest
public class SemesterRouteTest {
  @Test
  void runningThisTestInOctoberShouldIssueSecondSemester() {
    given().get("/semester").then().statusCode(200).body(is("SECOND semester"));
  }
}

It looks to be a good start. However, this test will obviously fail when executed from January until June. In other words, the test is not reproducible and it would be appreciable to fix this issue by mocking the monthBean.

@InjectMock to the rescue

Luckily, Quarkus is providing the @InjectMock annotation in order to inject mocks in the CDI bean registry. This annotation is packaged in the quarkus-junit5-mockito artifact, so maven users would need to add a dependency like below:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-junit5-mockito</artifactId>
  <scope>test</scope>
</dependency>

Camel is well integrated with the Quarkus registry, allowing us to write the following kind of tests:

@QuarkusTest
public class SemesterRouteTest {
  @InjectMock
  MonthBean monthBean;

  @Test
  void januaryShouldIssueFirstSemester() {
    when(monthBean.month()).thenReturn(1);
    given().get("/semester").then().statusCode(200).body(is("FIRST semester"));
  }
}

At first, notice how we used @InjectMock to define the MonthBean mock. And later, the Mockito statement when(monthBean.month()).thenReturn(1) let us influence the behavior of the mock. As such, we are now able to simulate that the month() method is called in January at will.

More good news

Not solely have we fixed the reproducibility issue, but we are even able to complete the test coverage with more scenarios:

@Test
void augustShouldIssueSecondSemester() {
  when(monthBean.month()).thenReturn(8);
  given().get("/semester").then().statusCode(200).body(is("SECOND semester"));
}

@Test
void exceptionShouldIssueHttp500() {
  doThrow(new IllegalArgumentException("Simulating an exception")).when(monthBean).month();
  given().get("/semester").then().statusCode(500);
}

Conclusion

So far, we have introduced a way to mock beans in Camel Quarkus tests. It helped us to define reproducible tests and to improve the test coverage. Note that @InjectMock works only in JVM Mode, yet it offers a good complement to native tests.

The source code used in this blog post is hosted on my github repository.

More information are available about the Quarkus mocking features in the great article from Georgios Andrianakis about Mocking CDI beans in Quarkus. Finally, I would like to thank Gerhard G. for the mocking camel picture.