Unit testing of the Messages App

In Chapter 2Vue.js 2 – It Works in the Way You Expected, we created a Messages App that has an API to retrieve all of the messages that are received. In this section, we will write unit testing code in that application to test that API.

Before writing any test code, we need to add spring-boot-starter-test in the Message App's pom.xml file, as shown in the following code. Let's have a look at the pom.xml file:

<project>
...
<dependencies>
...
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>

For this dependency, we use a test scope so that the related dependencies won't be included in the final package. This starter will add the following libraries to the application:

  • JUnit: The de facto standard for unit testing in Java applications. The version bundled in Spring Boot 2.0.0.RELEASE is JUnit 4.12.
  • Spring Test and Spring Boot Test: Utilities and integration test support for Spring Boot applications.
  • AssertJ: A fluent assertion library for Java.
  • Hamcrest: A library of matcher objects, which can be combined to create flexible expressions of intent in tests.
  • Mockito: A Java mocking framework.
  • JSONassert: An assertion library for writing JSON unit tests in less code.
  • JsonPath: A Java DSL for reading JSON documents.

The unit testing code for MessageController#getMessages() will be put inside a separate class named MessageControllerTest that lives in the /test/java/app/messages/web/ directory. All of the test classes in this book will follow the <Class>Test format. Here is what this test class looks like. Let's have a look at the MessageControllerTest.java file:

...
@RunWith(SpringRunner.class)
@WebMvcTest(MessageController.class)
public class MessageControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private MessageService service;
@Test
public void getMessages_existingMessages_shouldReturnJsonArray()
throws Exception {
Message firstMessage = new Message("First Message");
List<Message> allMessages = Arrays.asList(firstMessage);
when(service.getMessages()).thenReturn(allMessages);
mvc.perform(get("/api/messages").contentType(MediaType.
APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].text", is(firstMessage.getText())));
}
}

As you can see, we apply the @RunWith and @WebMvcTest annotations to set up this test class. The @RunWith annotation is a JUnit 4 annotation used to specify the JUnit Runner of this test class. A JUnit Runner is a class that extends JUnit's abstract Runner class and is used for running test classes. In our example, the runner will be SpringRunner, a class provided by the Spring Test framework. The @WebMvcTest annotation is provided by Spring. With its presence, Spring will only autoconfigure the Spring MVC's infrastructure.

Inside the test class, we have two properties: mvc of the MockMvc class, and service of the MessageService class, which is annotated by the @MockBean annotation. The MockMvc class is the main entry point for server-side Spring MVC test support, while the @MockBean annotation is used to create a mock of MessageService, which is then added to Spring's application context. The mock will also be injected into the service field.

The test method, getMessages_existingMessages_shouldReturnJsonArray(), follows the naming convention for unit testing that's suggested by Roy Osherove, which is [UnitOfWork_StateUnderTest_ExpectedBehavior]. The @Test annotation is from JUnit, which tells JUnit that the public void method that it annotated can be run as a test case. Inside this method, first, we create a list called allMessages that contains a Message object. Then, we use Mockito's when().thenReturn() command to set up the details of the service mock. When the MessageService#getMessage() method is invoked, the mock will return allMessages. In this way, we isolate the MessageController class from its dependencies and, at the same time, have full control of those dependencies.

When the pre-condition is ready, we use the mvc.perform() method to perform a GET request to the API and add assertions to verify the result. Here, we verify that Content-Type of the API's response is application/json, and that the status code is 200. We use JsonPath to verify that the resulting JSON has only one item and that the value of the text field is First Message.

In VS Code, you can simply click Run Test from the class to execute the unit test cases of that class only, as shown in the following screenshot. Or you can execute the mvn test command to run all of the unit testing together:

Figure 7.3: Test class in VS Code

Up until this point, we have successfully tested the MessageController#getMessages() method. In practice, we will write multiple test cases for a single method to verify the behavior of the method and understand its different conditions. We will talk more about unit testing later in this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.165.70