Book Spring Boot 2: Best Practices for Professionals

Increase the speed and ease of developing microservices and complex applications, eliminating the worries of Spring configuration.
Use Spring Boot 2 and Spring 5 framework tools like WebFlux, Security, Actuator, and the Micrometer framework, which provides a new way to collect metrics.
Spring Testing Framework
One of the main ideas of the Spring framework is to encourage developers to create simple and loosely coupled classes, programming interfaces, so that the software becomes more reliable and better extensible. The Spring framework provides tools that simplify unit and integration testing (in fact, if you really program interfaces, you don’t need to test the functionality of Spring applications). In other words, it is necessary that the application can be tested using JUnit or TestNG testing systems based on objects (created simply using the new operator – without Spring or any other container).
The Spring framework includes several packages designed for unit or integration testing of applications. For unit testing, several simulation objects are intended (Environment, PropertySource, JNDI, Servlet; reactive testing utilities ServerHttpRequest and ServerHttpResponse), with which you can perform isolation testing of code.
One of the most commonly used testing capabilities in the Spring framework is integration testing. Its main tasks:
- Managing Spring IoC container caching between test runs
- transaction management;
- Dependency injection of test object instances
- creation of base classes designed specifically for Spring.
The Spring framework provides an easy way to test by integrating into the application context tests (ApplicationContext). The Spring testing module offers several ways to use ApplicationContext programmatically and using annotations.
- Abstract BootstrapWith. Class level annotation for configuring the bootstrap of the TestContext Spring framework.
- @ContextConfiguration annotation. Defines class level metadata that defines how to load and configure ApplicationContext for integration tests. This is a must-have annotation for your classes, because this is where ApplicationContext loads all component definitions.
- Abstract @WebAppConfiguration. A class-level annotation indicating that the application context loaded for the integration test should be WebApplicationContext.
- Annotation @ActiveProfile. A class level annotation indicating which of the component definition profiles should be active when loading the ApplicationContext for the integration test.
- Abstract @TestPropertySource. A class level annotation designed to specify the locations of property files and embedded properties that are added to the PropertySource object set in Environment for the ApplicationContext loaded for the integration test.
- Abstract @DirtiesContext. Indicates that the used ApplicationContext was “dirty” during the test (for example, modified or damaged by changing the state of a single component) and should be closed.
These are far from all annotations, there are many others (@TestExecutionListeners, Commit, Rollback, @BeforeTransaction, @AfterTransaction, Sql, SqlGroup, SqlConfig, Timed, Repeat, @IfProfileValue, etc.).
As you can see, there are many testing options with the Spring framework. Usually the @RunWith annotation is always used, linking together all the elements of the testing framework. For instance:
@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class ToDoRepositoryTests {
@Test
public void ToDoPersistenceTest(){
//...
}
}
Now let’s see how to use the Spring Testing Framework and what features Spring Boot provides.
Spring Boot Testing Framework
Spring Boot leverages the power of the Spring Testing Framework, expanding on the old and adding new annotations and features that make testing easier for developers.
To start using all the features of Spring Boot testing, you just need to add the spring-boot-starter-test dependency to the application with the test (scope test) scope. The Spring Initializr service has already added this dependency.
The spring-boot-starter-test dependency provides the ability to use several testing frameworks that are very consistent with the Spring Boot testing capabilities: JUnit, AssertJ, Hamcrest, Mockito, JSONassert, and JsonPath. Of course, there are other testing frameworks that work fine with the Spring Boot Test module; just the corresponding dependencies need to be specified manually.
Spring Boot provides the @SpringBootTest annotation to simplify testing Spring applications. Typically, when testing a Spring application, you need to add a few annotations to test a specific application feature or functionality, but not in Spring Boot – although for testing you still need to specify the @RunWith annotation (SpringRunner.class); if this is not done, any new Spring Boot testing annotations will be ignored. The @SpringBootTest annotation has options useful for testing web applications, such as RANDOM_PORT and DEFINED_PORT.
The following code snippet is the Spring Boot test framework.
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
@Test
public void exampleTest() {
...
}
}
Web Application Endpoint Testing
Spring Boot provides a convenient way to test endpoints: a simulation environment called the MockMvc class:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockMvcToDoTests {
@Autowired
private MockMvc mvc;
@Test
public void toDoTest() throws Exception {
this.mvc
.perform(get("/todo"))
.andExpect(status().isOk())
.andExpect(content()
.contentType(MediaType.APPLICATION_JSON_UTF8));
}
}
You can also use the TestRestTemplate class.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ToDoSimpleRestTemplateTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void toDoTest() {
String body = this.restTemplate.getForObject("/todo", String.class);
assertThat(body).contains("Read a Book");
}
}
This code shows a test that starts a full server and uses an instance of the TestRestTemplate class to access the / todo endpoint. Here we assume that the String object is returned (this is not the best way to test JSON return; don’t worry, we will show how to use the TestRestTemplate class correctly).
Component imitation
The Spring Boot testing module provides an @MockBean annotation that describes a Mockito simulation object for a component in ApplicationContext. In other words, you can create an imitation of a new Spring component or replace an existing definition by adding this annotation. Remember: all this happens inside the ApplicationContext.
@RunWith(SpringRunner.class)
@SpringBootTest
public class ToDoSimpleMockBeanTests {
@MockBean
private ToDoRepository repository;
@Test
public void toDoTest() {
given(this.repository.findById("my-id"))
.Return(new ToDo("Read a Book"));
assertThat(
this.repository.findById("my-id").getDescription())
.isEqualTo("Read a Book");
}
}
Spring Boot Test Slices
One of the most important features of Spring Boot is running tests without the need for any specific infrastructure. The Spring Boot testing module includes so-called slices designed to test specific parts of an application without using a server or DBMS.
@JsonTest annotation
The Spring Boot testing module has an @JsonTest annotation that simplifies serialization / deserialization of JSON objects and checks to see if everything works correctly. @JsonTest automatically configures the supported JSON display tool, depending on the library found on the class path: Jackson, GSON, or JSONB.
@RunWith(SpringRunner.class)
@JsonTest
public class ToDoJsonTests {
@Autowired
private JacksonTester json;
@Test
public void toDoSerializeTest() throws Exception {
ToDo toDo = new ToDo("Read a Book");
assertThat(this.json.write(toDo))
.isEqualToJson("todo.json");
assertThat(this.json.write(toDo))
.hasJsonPathStringValue("@.description");
assertThat(this.json.write(toDo))
.extractingJsonPathStringValue("@.description")
.isEqualTo("Read a Book");
}
@Test
public void toDoDeserializeTest() throws Exception {
String content = "{"description":"Read a Book","completed":
true }";
assertThat(this.json.parse(content))
.isEqualTo(new ToDo("Read a Book", true));
assertThat(
this.json.parseObject(content).getDescription())
.isEqualTo("Read a Book");
}
}
To test controllers without using a full-fledged server, you can use the Spring Boot proposed annotation @WebMvcTest, which automatically configures the Spring MVC infrastructure and restricts the list of viewed components to the following: Controller, ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver; thanks to this, you will know if your controllers work as expected.
It is important to understand that components marked as Component are not visible when using this annotation, but you can use the @MockBean annotation if necessary.
@RunWith(SpringRunner.class)
@WebMvcTest(ToDoController.class)
public class ToDoWebMvcTest {
@Autowired
private MockMvc mvc;
@MockBean
private ToDoRepository toDoRepository;
@Test
public void toDoControllerTest() throws Exception {
given(this.toDoRepository.findById("my-id"))
.Return(new ToDo("Do Homework", true));
this.mvc.perform(get("/todo/my-id").accept(MediaType.APPLICATION_
JSON_UTF8))
.andExpect(status().isOk()).andExpect(content().
string("{"id":"my-id","description":"Do Homework",
"completed":true}"));
}
}
@WebFluxTest annotation
For reactive controllers, Spring Boot provides the @WebFluxTest annotation. This annotation automatically configures the Spring WebFlux module infrastructure and only searches for Controller, ControllerAdvice, @JsonComponent, Converter, GenericConverter and WebFluxConfigurer.
It is important to understand that components marked as Component are not visible when using this annotation, but you can use the @MockBean annotation if necessary.
@RunWith(SpringRunner.class)
@WebFluxTest(ToDoFluxController.class)
public class ToDoWebFluxTest {
@Autowired
private WebTestClient webClient;
@MockBean
private ToDoRepository toDoRepository;
@Test
public void testExample() throws Exception {
given(this.toDoRepository.findAll())
.Return(Arrays.asList(new ToDo("Read a Book"), new
ToDo("Buy Milk")));
this.webClient.get().uri("/todo-flux").accept(MediaType.
APPLICATION_JSON_UTF8)
.exchange()
.expectStatus().isOk()
.expectBody(List.class);
}
}
@DataJpaTest annotation
For testing JPA applications, the Spring Boot testing module provides the @DataJpaTest annotation, which automatically configures the built-in databases located in RAM. It searches for Entity and does not load any Component components. In addition, it provides a test-oriented helper class TestEntityManager, very similar to the JPA EntityManager class.
@RunWith(SpringRunner.class)
@DataJpaTest
public class TodoDataJpaTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private ToDoRepository repository;
@Test
public void toDoDataTest() throws Exception {
this.entityManager.persist(new ToDo("Read a Book"));
Iterable toDos = this.repository.
findByDescriptionContains("Read a Book");
assertThat(toDos.iterator().next()).toString().contains("Read a Book");
}
}
Please note that when testing with @DataJpaTest, built-in DBMSs in RAM are used. For testing with a real database, you must provide the test class with the annotation @AutoConfigureTestDatabase (replace = Replace.NONE).
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class TodoDataJpaTests {
//...
}
@JdbcTest annotation
This annotation is very similar to @DataJpaTest; the only difference is that it runs exclusively on JDBC tests. It automatically configures the built-in DBMS located in the RAM and the JdbcTemplate class, while skipping all the annotated Component classes.
@RunWith(SpringRunner.class)
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class TodoJdbcTests {
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
private CommonRepository repository;
@Test
public void toDoJdbcTest() {
ToDo toDo = new ToDo("Read a Book");
this.repository = new ToDoRepository(jdbcTemplate);
this.repository.save(toDo);
ToDo result = this.repository.findById(toDo.getId());
assertThat(result.getId()).isEqualTo(toDo.getId());
}
}
@DataMongoTest annotation
For testing MongoDB applications, the Spring Boot testing module provides the @DataMongoTest annotation. It automatically configures the built-in, memory-based Mongo server, if available; if not, you need to add the necessary properties of spring.data.mongodb. *. It also tunes the MongoTemplate class and looks for @Document annotations. Component components are skipped.
@RunWith(SpringRunner.class)
@DataMongoTest
public class TodoMongoTests {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void toDoMongoTest() {
ToDo toDo = new ToDo("Read a Book");
this.mongoTemplate.save(toDo);
ToDo result = this.mongoTemplate.findById(toDo.getId(),ToDo.class);
assertThat(result.getId()).isEqualTo(toDo.getId());
}
}
If you need an external MongoDB server (non-embedded, in-memory) add the excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class parameter to the @DataMongoTest annotation.
@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class ToDoMongoTests {
// ...
}
@RestClientTest annotation
Another important annotation is @RestClientTest, designed to test REST clients. This annotation automatically makes settings to support Jackson, GSON, and JSONB, and also sets up the RestTemplateBuilder class and adds support for MockRestServiceServer.
@RunWith(SpringRunner.class)
@RestClientTest(ToDoService.class)
public class ToDoRestClientTests {
@Autowired
private ToDoService service;
@Autowired
private MockRestServiceServer server;
@Test
public void toDoRestClientTest()
throws Exception {
String content = "{"description":"Read a Book","completed":
true }";
this.server.expect(requestTo("/todo/my-id"))
.andRespond(withSuccess(content,MediaType.APPLICATION_JSON_UTF8));
ToDo result = this.service.findById("my-id");
assertThat(result).isNotNull();
assertThat(result.getDescription()).contains("Read a Book");
}
}
There are many other slices available for use. The main thing to remember: for testing, a complete infrastructure with all running servers is optional. Slices make it easier to test Spring Boot applications.
about the author
Felipe Gutierrez (Felipe Gutierrez) is a software architect who holds bachelor’s and master’s degrees in computer engineering from the Institute of Technology and Higher Education in Monterrey, Mexico. Gutierrez has over 20 years of IT experience and has developed programs for companies from a variety of vertically integrated industries such as government, retail, healthcare, education and banking. He currently works at Pivotal, specializing in PAS and PKS for Cloud Foundry, Spring framework, native cloud applications Spring, Groovy and RabbitMQ, among other technologies. He has also been a software architect for large companies such as Nokia, Apple, Redbox, and Qualcomm. Gutierrez is the author of Spring Boot Messaging (Apress, 2017) and Introducing Spring Framework (Apress, 2014).
About science editors
Original edition
Manuel Jordan Helera (Manuel Jordan Elera) – a self-taught developer and researcher, loves to learn new technologies for his experiments and their new combinations. Manuel won the Springy Award Community Champion and Spring Champion 2013. He devotes a little free time to reading the Bible and composing guitar music. Manuel is known by the internet pseudonym dr_pompeii. He has edited many books scientifically, including Pro Spring, 4th Edition (Apress, 2014) 1, Practical Spring LDAP (Apress, 2013), Pro JPA 2, 2nd Edition (Apress, 2013), and Pro Spring Security (Apress , 2013).
Russian edition
Valery Alekseevich Dmitrushchenkov Has been working in IT for over 35 years. He developed software for many companies and industries, managed many complex projects, including the development, implementation and maintenance of automated systems. He participated in the creation of large projects for government bodies implemented by international organizations: the United Nations, USIAD, World Bank in Russia, Kosovo, Moldova and Armenia.
»More details on the book can be found at publishing site
” Excerpt
For Khabrozhiteley 25% discount on the coupon – Spring boot
Upon payment of the paper version of the book, an electronic book is sent by e-mail.