How to build a full-fledged backend architecture in Java - Part II

Full-fledged backend architecture from our  previous article. Source: Author.

How to build a full-fledged backend architecture in Java - Part II

In the previous article you learned how to build a full-fledged backend architecture in Java. In this article, you’ll learn how to test the functionality you just built.

Testing

As experienced software developers, it is indispensable for us to create unit tests for every single functionality we write. Nonetheless, for the present case we are facing two challenges:
1. How to call our API? – We need a mechanism to simulate frontend calling our API, send the proper parameters in the request, catch the response and validate its correctness.
2. How to fake the response of our client’s API? – We’re able to call an external service, but… it is not there. Thus we need an instrument to return a fake/mocked response, once the call is executed.

Introducing RestAssured

RestAssured is a Java library that allows us to easily test our REST endpoints by simulating frontend calls to our API. It also provides the functionality to assert the validity of the responses.
RestAssured allows us to perform a call to our endpoint and validate that the response we get from it is the expected one. 

They key methods are:
ü  Http Methods: get(), post(), put(), delete(), options(), patch(), head() Performs a call to the specified endpoint using the selected HTTP Method.
ü  Then() – Everything that comes after this method is an assertion. We can validate for instance:
ü  statusCode() – HTTP Status code of the response
ü  body() – Check the contents of the response. We can check individual fields in the following manner:
.body("id", notNullValue())
.body("id",5)
.body("status",equalTo("SUCCESS"))
Note that we use RestAssured in conjunction with org.hamcrest.Matchers. 
With the help of RestAssured we are able to call our own API and thereby solve problem #1. What about problem #2?

Introducing Restito 

Restito is a library that:
ü  Mimics rest server behavior
ü  Records HTTP calls to the server
ü  Performs verification against happened calls


According to the documentation:
“Restito sets up a StubServer instance which responds to your application's Calls based on defined Stubs. A stub makes some Action when Condition is satisfied.”

Colloquially, we can mock the response we’ll get from the external service. To set restito up, we follow the next procedure:
1.      Set up a Stub server, which will be listening to a specific port.
2.      Add the conditions that the request should meet. These can be:
a.      Match() – Here you can specify the endpoint, the HTTP method to which the server will respond, and the request including body and headers. 
b.      Then() – Allows us to create the expected server response, including HTTP status and body of the response.
Perfect! Thanks to Restito and RestAssured you can fully test your endpoint. Now, let’s get our hands on the code.

Code!

Now we’ll create a new class for our tests. Let’s call it: UsersValidationsTest.java
We need to annotate this class properly and Spring provides several options for this purpose. Some of these options are:
ü  @SpringBootTest – Used to perform complete integration tests with all the elements of the backend. The @SpringBootTest annotation tells Spring Boot to go and look for the main configuration class (one with @SpringBootApplication for instance), and use that to start a Spring application context. [Spring Guides]
ü  @WebMvcTest – Performs tests on the web application layer. Generally used to test controllers without calling internal services. The latter are mocked through the annotation @MockBean
ü  @DataJpaTest provides some standard setup needed for testing the persistence layer. [Baeldung]


To make our test more comprehensive, we’ll create an E2E test that will test all the layers of our architecture. Hence, the annotation @SpringBootTest is the appropriate one in our case.

Our class now looks as follows:

UsersValidationsTest.java
@RunWith(SpringRunner.class)

@SpringBootTest(classes = RestTestDemoApplication.class, 
 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class UsersValidationsTest {
}

Next step is to set restito up. From the examples, we need to create the stub server, start it, and stop it after the test. For this purpose, we’ll create an object called externalServiceServer and start/stop it using the annotations @BeforeClass and @AfterClass, respectively.

protected static StubServer externalServiceServer;
@BeforeClass
public synchronized static void start() {
    externalServiceServer = new StubServer(8000).run();
}

@AfterClass
public static void stop() {
    externalServiceServer.stop();
}

In regard to the test itself, there are two possible scenarios: 
ü  Either the username exists, and the API returns HTTP Status 302
ü  Or the username is not registered, and the API returns HTTP Status 404.

For the scope of this tutorial we’ll test only case number one.

We’ll create our test function. Let’s name it checkExistingUsername. Inside it, we have to:
1.      Create the object for the expected response from the external service.
2.      Finish setting restito up by executing step #2 from the introduction to Restito. 
3.      Execute the API and validate the response.

The final @Test method will look as follows:
@Test
public void checkExistingUsername() throws JsonProcessingException {

    //1. Create the object for the expected response from the external service.
    String username = "14c4b06b824ec593239362517f538b29";
    UserFeignClientResponse externalServiceResponse = 
 new UserFeignClientResponse("c4ca4238a0b923820dcc509a6f75849b",
            "Foo User",
            "Foo",
            new Date(),
            username);

    //2. Finish setting up restito
    ObjectMapper mapper = new ObjectMapper();
    whenHttp(externalServiceServer).match(Condition.get("/user/get/" + username))
            .then(
                    Action.stringContent(mapper.writeValueAsString(
     externalServiceResponse)),
                    Action.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE),
                    Action.status(HttpStatus.OK_200));

    // 3. Execute the API and validate the response.
    RestAssured
            .given()
            .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
            .when()
            .get(path + "/users/exists/" + username)
            .then()
            .statusCode(HttpStatus.FOUND_302.getStatusCode());
}

Now, the moment of truth has come. Let’s test our API:
Figure 1. Tests passed!

Aaaaaaaaand THERE YOU GO! Our API and its architecture work as expected. 

You can download the code for this tutorial from Github!

In this tutorial, you learned how to build and test a robust backend architecture, which respects the separation of concerns and makes your code cleaner, easier to understand and maintain. 

Now it’s your turn to start applying this knowledge to your personal and corporate projects.
Stay tuned for more in-depth tutorials! Hasta la vista!

Comments