existingBook = bookRepository.findById(book.getIsbn());
+ if (existingBook.isPresent()) {
+ throw new DuplicateBookException(book);
+ }
+
+ final BookData savedBook = bookRepository.add(convertBook(book));
+ return convertBookData(savedBook);
+ }
+
+ private static Book convertBookData(BookData bookData) {
+ return new Book(bookData.getIsbn(), bookData.getName(), bookData.getAuthor());
+ }
+
+ private static BookData convertBook(Book book) {
+ return new BookData(book.getIsbn(), book.getName(), book.getAuthor());
+ }
+}
diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties b/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties
new file mode 100644
index 0000000000..56638f8c1a
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+server.servlet.context-path=/spring-boot-jsp
+
+spring.mvc.view.prefix: /WEB-INF/jsp/
+spring.mvc.view.suffix: .jsp
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css b/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css
new file mode 100644
index 0000000000..a32d81c6a2
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css
@@ -0,0 +1,10 @@
+table {
+ font-family: arial, sans-serif;
+ border-collapse: collapse;
+}
+
+td, th {
+ border: 1px solid #dddddd;
+ text-align: left;
+ padding: 8px;
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html b/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html
new file mode 100644
index 0000000000..c27bd8bb7a
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html
@@ -0,0 +1,10 @@
+
+
+
+
+ Error
+
+
+Opps! 4xx Error Occurred.
+
+
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp
new file mode 100644
index 0000000000..8195743da8
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp
@@ -0,0 +1,21 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+
+
+ Add Book
+
+
+
+ Successfully added Book with ISBN: ${savedBook.isbn}
+
+
+
+
+ ISBN:
+ Book Name:
+ Author Name:
+
+
+
+
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp
new file mode 100644
index 0000000000..6db90ca5c7
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp
@@ -0,0 +1,18 @@
+<%--
+ Created by IntelliJ IDEA.
+ User: jason
+ Date: 3/13/21
+ Time: 10:39 PM
+ To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+
+
+ Error
+
+
+ Reference: ${ref}
+ Error Message: ${message}
+ Object: ${object}
+
+
diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp
new file mode 100644
index 0000000000..4a8e00a69b
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp
@@ -0,0 +1,28 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+ View Books
+ " rel="stylesheet" type="text/css">
+
+
+
+
+
+ ISBN |
+ Name |
+ Author |
+
+
+
+
+
+ ${book.isbn} |
+ ${book.name} |
+ ${book.author} |
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerIntegrationTest.java b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerIntegrationTest.java
new file mode 100644
index 0000000000..1847cbf545
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerIntegrationTest.java
@@ -0,0 +1,93 @@
+package com.baeldung.boot.jsp.controller;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasProperty;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+
+import java.util.Collections;
+import java.util.Optional;
+
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import com.baeldung.boot.jsp.repository.BookRepository;
+import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository;
+import com.baeldung.boot.jsp.repository.model.BookData;
+
+@ExtendWith(SpringExtension.class)
+@WebAppConfiguration
+@ContextConfiguration
+@AutoConfigureMockMvc
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class BookControllerIntegrationTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private BookRepository bookRepository;
+
+ @Test
+ @Order(1)
+ public void whenAddBook_thenBookSaved() throws Exception {
+ MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
+ .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ .param("isbn", "isbn1")
+ .param("name", "name1")
+ .param("author", "author1");
+ mockMvc.perform(addBookRequest)
+ .andReturn();
+
+ Optional storedBookOpt = bookRepository.findById("isbn1");
+ assertTrue(storedBookOpt.isPresent());
+ assertEquals("name1", storedBookOpt.get()
+ .getName());
+ assertEquals("author1", storedBookOpt.get()
+ .getAuthor());
+ }
+
+ @Test
+ @Order(2)
+ public void givenAlreadyExistingBook_whenAddBook_thenShowErrorPage() throws Exception {
+ MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
+ .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ .param("isbn", "isbn1")
+ .param("name", "name1")
+ .param("author", "author1");
+ ResultActions addBookResult = mockMvc.perform(addBookRequest);
+
+ addBookResult.andExpect(view().name("error-book"))
+ .andExpect(model().attribute("ref", "isbn1"))
+ .andExpect(model().attribute("object", hasProperty("isbn", equalTo("isbn1"))))
+ .andExpect(model().attribute("message", "Cannot add an already existing book"));
+ }
+
+ @Configuration
+ @ComponentScan("com.baeldung.boot.jsp")
+ static class ContextConfiguration {
+
+ @Bean
+ public BookRepository provideBookRepository() {
+ return new InMemoryBookRepository(Collections.emptyMap());
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerUnitTest.java b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerUnitTest.java
new file mode 100644
index 0000000000..af1d3d4956
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/controller/BookControllerUnitTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.boot.jsp.controller;
+
+import static org.hamcrest.Matchers.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.AdditionalAnswers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+import com.baeldung.boot.jsp.dto.Book;
+import com.baeldung.boot.jsp.service.BookService;
+
+@WebMvcTest(BookController.class)
+class BookControllerUnitTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @MockBean
+ private BookService bookService;
+
+ @Test
+ public void whenViewBooks_thenReturnBooksView() throws Exception {
+ when(bookService.getBooks()).thenReturn(existingBooks());
+ ResultActions viewBooksResult = mockMvc.perform(get("/book/viewBooks"));
+
+ viewBooksResult.andExpect(view().name("view-books"))
+ .andExpect(model().attribute("books", hasSize(3)));
+ }
+
+ @Test
+ public void whenAddBookView_thenReturnAddBooksView() throws Exception {
+ ResultActions addBookViewResult = mockMvc.perform(get("/book/addBook"));
+
+ addBookViewResult.andExpect(view().name("add-book"))
+ .andExpect(model().attribute("book", isA(Book.class)));
+ }
+
+ @Test
+ public void whenAddBookPost_thenRedirectToAddBookView() throws Exception {
+ when(bookService.addBook(any(Book.class))).thenAnswer(AdditionalAnswers.returnsFirstArg());
+ MockHttpServletRequestBuilder addBookRequest = MockMvcRequestBuilders.post("/book/addBook")
+ .contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+ .param("isbn", "isbn1")
+ .param("name", "name1")
+ .param("author", "author1");
+ ResultActions addBookResult = mockMvc.perform(addBookRequest);
+
+ addBookResult.andExpect(status().is3xxRedirection())
+ .andExpect(redirectedUrl("/book/addBook"))
+ .andExpect(flash().attribute("savedBook", hasProperty("isbn", equalTo("isbn1"))))
+ .andExpect(flash().attribute("addBookSuccess", true));
+ }
+
+ private static Collection existingBooks() {
+ List books = new ArrayList<>();
+ books.add(new Book("isbn1", "name1", "author1"));
+ books.add(new Book("isbn2", "name2", "author2"));
+ books.add(new Book("isbn3", "name3", "author3"));
+ return books;
+ }
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepositoryUnitTest.java b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepositoryUnitTest.java
new file mode 100644
index 0000000000..83f0c19e26
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepositoryUnitTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.boot.jsp.repository.impl;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.*;
+
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.boot.jsp.repository.BookRepository;
+import com.baeldung.boot.jsp.repository.model.BookData;
+
+public class InMemoryBookRepositoryUnitTest {
+
+ @Test
+ public void givenEmtpyData_whenFindAll_thenReturnEmptyCollection() {
+ BookRepository bookRepository = new InMemoryBookRepository(Collections.emptyMap());
+ Collection storedBooks = bookRepository.findAll();
+
+ assertEquals(0, storedBooks.size());
+ }
+
+ @Test
+ public void givenInitialData_whenFindAll_thenReturnInitialData() {
+ BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
+ Collection storedBooks = bookRepository.findAll();
+
+ assertEquals(3, storedBooks.size());
+ }
+
+ @Test
+ public void givenInitialData_whenFindUnavailableIsbn_thenReturnEmpty() {
+ BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
+ Optional storedBookOpt = bookRepository.findById("isbn4");
+
+ assertFalse(storedBookOpt.isPresent());
+ }
+
+ @Test
+ public void givenInitialData_whenFindAvailableIsbn_thenReturnItem() {
+ BookRepository bookRepository = new InMemoryBookRepository(initialBookData());
+ Optional storedBookOpt = bookRepository.findById("isbn1");
+
+ assertTrue(storedBookOpt.isPresent());
+ }
+
+ @Test
+ public void givenAddedIsbn_whenFindAvailableIsbn_thenReturnItem() {
+ BookRepository bookRepository = new InMemoryBookRepository(Collections.emptyMap());
+ bookRepository.add(new BookData("isbn4", "name4", "author4"));
+ Optional storedBookOpt = bookRepository.findById("isbn4");
+
+ assertTrue(storedBookOpt.isPresent());
+ }
+
+ private static Map initialBookData() {
+ Map initData = new HashMap<>();
+ initData.put("isbn1", new BookData("isbn1", "name1", "author1"));
+ initData.put("isbn2", new BookData("isbn2", "name2", "author2"));
+ initData.put("isbn3", new BookData("isbn3", "name3", "author3"));
+ return initData;
+ }
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/BookServiceIntegrationTest.java b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/BookServiceIntegrationTest.java
new file mode 100644
index 0000000000..4223f3f970
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/BookServiceIntegrationTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.boot.jsp.service;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.boot.jsp.dto.Book;
+import com.baeldung.boot.jsp.exception.DuplicateBookException;
+import com.baeldung.boot.jsp.repository.BookRepository;
+import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository;
+import com.baeldung.boot.jsp.repository.model.BookData;
+
+@ExtendWith(SpringExtension.class)
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
+public class BookServiceIntegrationTest {
+
+ @Autowired
+ private BookService bookService;
+
+ @Test
+ @Order(1)
+ public void givenNoAddedBooks_whenGetAllBooks_thenReturnInitialBooks() {
+ Collection storedBooks = bookService.getBooks();
+
+ assertEquals(3, storedBooks.size());
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-1"))));
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-2"))));
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("ISBN-TEST-3"))));
+ }
+
+ @Test
+ @Order(2)
+ public void givenBookNotAlreadyExists_whenAddBook_thenReturnSuccessfully() {
+ Book bookToBeAdded = new Book("ISBN-ADD-TEST-4", "Added Book 4", "Added Book 4 Author");
+ Book storedBook = bookService.addBook(bookToBeAdded);
+
+ assertEquals(bookToBeAdded.getIsbn(), storedBook.getIsbn());
+ }
+
+ @Test
+ @Order(3)
+ public void givenBookAlreadyExists_whenAddBook_thenDuplicateBookException() {
+ Book bookToBeAdded = new Book("ISBN-ADD-TEST-4", "Updated Book 4", "Updated Book 4 Author");
+
+ assertThrows(DuplicateBookException.class, () -> bookService.addBook(bookToBeAdded));
+ }
+
+ @Configuration
+ @ComponentScan("com.baeldung.boot.jsp")
+ static class ContextConfiguration {
+
+ @Bean
+ public BookRepository provideBookRepository() {
+ return new InMemoryBookRepository(initialBookData());
+ }
+
+ private static Map initialBookData() {
+ Map initData = new HashMap<>();
+ initData.put("ISBN-TEST-1", new BookData("ISBN-TEST-1", "Book 1", "Book 1 Author"));
+ initData.put("ISBN-TEST-2", new BookData("ISBN-TEST-2", "Book 2", "Book 2 Author"));
+ initData.put("ISBN-TEST-3", new BookData("ISBN-TEST-3", "Book 3", "Book 3 Author"));
+ return initData;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/impl/BookServiceImplUnitTest.java b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/impl/BookServiceImplUnitTest.java
new file mode 100644
index 0000000000..defbf71fd9
--- /dev/null
+++ b/spring-web-modules/spring-boot-jsp/src/test/java/com/baeldung/boot/jsp/service/impl/BookServiceImplUnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.boot.jsp.service.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.AdditionalAnswers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import com.baeldung.boot.jsp.dto.Book;
+import com.baeldung.boot.jsp.exception.DuplicateBookException;
+import com.baeldung.boot.jsp.repository.BookRepository;
+import com.baeldung.boot.jsp.repository.model.BookData;
+import com.baeldung.boot.jsp.service.BookService;
+
+@ExtendWith(MockitoExtension.class)
+public class BookServiceImplUnitTest {
+
+ @Mock
+ private BookRepository bookRepository;
+
+ @Test
+ public void whenGetBooks_thenAllBooksReturned() {
+ when(bookRepository.findAll()).thenReturn(existingBooks());
+ BookService bookService = new BookServiceImpl(bookRepository);
+
+ Collection storedBooks = bookService.getBooks();
+ assertEquals(3, storedBooks.size());
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn1"))));
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn2"))));
+ assertThat(storedBooks, hasItem(hasProperty("isbn", equalTo("isbn3"))));
+ }
+
+ @Test
+ public void whenAddBook_thenAddSuccessful() {
+ when(bookRepository.findById(anyString())).thenReturn(Optional.empty());
+ when(bookRepository.add(any(BookData.class))).thenAnswer(AdditionalAnswers.returnsFirstArg());
+ BookService bookService = new BookServiceImpl(bookRepository);
+ Book book = bookService.addBook(new Book("isbn1", "name1", "author1"));
+
+ assertEquals("isbn1", book.getIsbn());
+ assertEquals("name1", book.getName());
+ assertEquals("author1", book.getAuthor());
+ }
+
+ @Test
+ public void givenBookAlreadyExist_whenAddBook_thenDuplicateBookException() {
+ BookData existingBook = new BookData("isbn1", "name1", "author1");
+ when(bookRepository.findById("isbn1")).thenReturn(Optional.of(existingBook));
+ BookService bookService = new BookServiceImpl(bookRepository);
+ Book bookToBeAdded = new Book("isbn1", "name1", "author1");
+
+ assertThrows(DuplicateBookException.class, () -> bookService.addBook(bookToBeAdded));
+ }
+
+ private static Collection existingBooks() {
+ List books = new ArrayList<>();
+ books.add(new BookData("isbn1", "name1", "author1"));
+ books.add(new BookData("isbn2", "name2", "author2"));
+ books.add(new BookData("isbn3", "name3", "author3"));
+ return books;
+ }
+}
\ No newline at end of file
diff --git a/spring-web-modules/spring-mvc-basics-2/pom.xml b/spring-web-modules/spring-mvc-basics-2/pom.xml
index 0b4515994b..adc42d8db8 100644
--- a/spring-web-modules/spring-mvc-basics-2/pom.xml
+++ b/spring-web-modules/spring-mvc-basics-2/pom.xml
@@ -131,14 +131,6 @@
json
${json.version}
-
- org.apache.maven.surefire
- surefire-logger-api
- ${maven-surefire-plugin.version}
-
- test
- true
-
@@ -163,7 +155,6 @@
1.8
1.8
- 2.21.0
2.3.2-b02
4.0.0
6.0.10.Final
diff --git a/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties
index cf26fbfb60..b8a9be0b40 100644
--- a/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties
+++ b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties
@@ -5,6 +5,3 @@ spring.mvc.pathmatch.use-suffix-pattern=true
#spring.mvc.contentnegotiation.favor-path-extension=true
#spring.mvc.contentnegotiation.favor-parameter=true
#spring.mvc.contentnegotiation.parameter-name=mediaType
-
-# https://github.com/spring-projects/spring-boot/issues/24207
-spring.main.allow-bean-definition-overriding=true
diff --git a/spring-web-modules/spring-mvc-views/pom.xml b/spring-web-modules/spring-mvc-views/pom.xml
index 2e80a60966..649814263c 100644
--- a/spring-web-modules/spring-mvc-views/pom.xml
+++ b/spring-web-modules/spring-mvc-views/pom.xml
@@ -111,7 +111,6 @@
- 1.8
2.3.3
4.0.1
5.2.1.RELEASE
diff --git a/spring-web-modules/spring-rest-http-2/pom.xml b/spring-web-modules/spring-rest-http-2/pom.xml
index 0ea3fd6840..a349ac1116 100644
--- a/spring-web-modules/spring-rest-http-2/pom.xml
+++ b/spring-web-modules/spring-rest-http-2/pom.xml
@@ -44,12 +44,13 @@
io.github.resilience4j
resilience4j-timelimiter
- 1.6.1
+ ${resilience4j.version}
2.9.2
+ 1.6.1
diff --git a/testing-modules/junit-5-advanced/pom.xml b/testing-modules/junit-5-advanced/pom.xml
index 4756223c3d..f53af9347f 100644
--- a/testing-modules/junit-5-advanced/pom.xml
+++ b/testing-modules/junit-5-advanced/pom.xml
@@ -35,18 +35,8 @@
-
-
-
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
-
-
-
5.4.2
- 2.21.0
5.4.2
diff --git a/testing-modules/junit-5-basics/pom.xml b/testing-modules/junit-5-basics/pom.xml
index b9c9635dc4..cdb0c367ce 100644
--- a/testing-modules/junit-5-basics/pom.xml
+++ b/testing-modules/junit-5-basics/pom.xml
@@ -152,7 +152,6 @@
1.2.0
5.4.2
5.0.6.RELEASE
- 2.21.0
diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml
index 831fa97e12..ded3e9e26d 100644
--- a/testing-modules/junit-5/pom.xml
+++ b/testing-modules/junit-5/pom.xml
@@ -105,10 +105,6 @@
-
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
org.codehaus.mojo
exec-maven-plugin
diff --git a/testing-modules/junit5-migration/pom.xml b/testing-modules/junit5-migration/pom.xml
index 3b2663d81d..e3ef21f506 100644
--- a/testing-modules/junit5-migration/pom.xml
+++ b/testing-modules/junit5-migration/pom.xml
@@ -18,12 +18,12 @@
org.junit.platform
junit-platform-engine
- ${junit.platform.version}
+ ${junit-platform.version}
org.junit.platform
junit-platform-runner
- ${junit.platform.version}
+ ${junit-platform.version}
test
@@ -48,17 +48,6 @@
-
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
-
- org.junit.platform
- junit-platform-surefire-provider
- ${junit.platform.version}
-
-
-
org.codehaus.mojo
exec-maven-plugin
@@ -79,7 +68,7 @@
5.2.0
- 1.2.0
+ 1.2.0
5.2.0
2.21.0
1.6.0
diff --git a/testing-modules/mockito-3/.gitignore b/testing-modules/mockito-3/.gitignore
new file mode 100644
index 0000000000..38fe5148c1
--- /dev/null
+++ b/testing-modules/mockito-3/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.settings/
+/.classpath
+/.project
\ No newline at end of file
diff --git a/testing-modules/mockito-3/README.md b/testing-modules/mockito-3/README.md
new file mode 100644
index 0000000000..c9766031a3
--- /dev/null
+++ b/testing-modules/mockito-3/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Mocking Static Methods With Mockito](https://www.baeldung.com/mockito-mock-static-methods)
diff --git a/testing-modules/mockito-3/pom.xml b/testing-modules/mockito-3/pom.xml
new file mode 100644
index 0000000000..8d506561ed
--- /dev/null
+++ b/testing-modules/mockito-3/pom.xml
@@ -0,0 +1,38 @@
+
+
+ 4.0.0
+ mockito-3
+ 0.0.1-SNAPSHOT
+ mockito-3
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+ org.mockito
+ mockito-inline
+ ${mockito.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+
+ 3.8.0
+ 3.8.0
+
+
+
diff --git a/testing-modules/mockito-3/src/main/java/com/baeldung/mockito/mockedstatic/StaticUtils.java b/testing-modules/mockito-3/src/main/java/com/baeldung/mockito/mockedstatic/StaticUtils.java
new file mode 100644
index 0000000000..2e2f5ead33
--- /dev/null
+++ b/testing-modules/mockito-3/src/main/java/com/baeldung/mockito/mockedstatic/StaticUtils.java
@@ -0,0 +1,22 @@
+package com.baeldung.mockito.mockedstatic;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class StaticUtils {
+
+ private StaticUtils() {
+ }
+
+ public static List range(int start, int end) {
+ return IntStream.range(start, end)
+ .boxed()
+ .collect(Collectors.toList());
+ }
+
+ public static String name() {
+ return "Baeldung";
+ }
+
+}
diff --git a/testing-modules/mockito-3/src/main/resources/logback.xml b/testing-modules/mockito-3/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/testing-modules/mockito-3/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing-modules/mockito-3/src/test/java/com/baeldung/mockito/mockedstatic/MockedStaticUnitTest.java b/testing-modules/mockito-3/src/test/java/com/baeldung/mockito/mockedstatic/MockedStaticUnitTest.java
new file mode 100644
index 0000000000..a212e6e3eb
--- /dev/null
+++ b/testing-modules/mockito-3/src/test/java/com/baeldung/mockito/mockedstatic/MockedStaticUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.mockito.mockedstatic;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.Arrays;
+
+class MockedStaticUnitTest {
+
+ @Test
+ void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
+ assertThat(StaticUtils.name()).isEqualTo("Baeldung");
+
+ try (MockedStatic utilities = Mockito.mockStatic(StaticUtils.class)) {
+ utilities.when(StaticUtils::name).thenReturn("Eugen");
+ assertThat(StaticUtils.name()).isEqualTo("Eugen");
+ }
+
+ assertThat(StaticUtils.name()).isEqualTo("Baeldung");
+ }
+
+ @Test
+ void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
+ assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
+
+ try (MockedStatic utilities = Mockito.mockStatic(StaticUtils.class)) {
+ utilities.when(() -> StaticUtils.range(2, 6))
+ .thenReturn(Arrays.asList(10, 11, 12));
+
+ assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
+ }
+
+ assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
+ }
+
+}
diff --git a/testing-modules/parallel-tests-junit/math-test-functions/pom.xml b/testing-modules/parallel-tests-junit/math-test-functions/pom.xml
index fb12803333..fdd45e19d6 100644
--- a/testing-modules/parallel-tests-junit/math-test-functions/pom.xml
+++ b/testing-modules/parallel-tests-junit/math-test-functions/pom.xml
@@ -27,7 +27,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.0
+ ${maven-surefire-plugin.version}
all
10
@@ -45,4 +45,8 @@
+
+ 2.22.0
+
+
diff --git a/testing-modules/parallel-tests-junit/string-test-functions/pom.xml b/testing-modules/parallel-tests-junit/string-test-functions/pom.xml
index 313d82c23f..727a1f814a 100644
--- a/testing-modules/parallel-tests-junit/string-test-functions/pom.xml
+++ b/testing-modules/parallel-tests-junit/string-test-functions/pom.xml
@@ -27,7 +27,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.0
+ ${maven-surefire-plugin.version}
all
true
@@ -37,4 +37,8 @@
+
+ 2.22.0
+
+
diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml
index fd4a13d026..228e47838c 100644
--- a/testing-modules/pom.xml
+++ b/testing-modules/pom.xml
@@ -16,34 +16,35 @@
assertion-libraries
easy-random
+ easymock
gatling
groovy-spock
+ hamcrest
+ junit-4
+ junit-5-advanced
+ junit-5-basics
junit-5
junit5-annotations
junit5-migration
load-testing-comparison
- mockito
mockito-2
- hamcrest
+ mockito-3
+ mockito
mocks
mockserver
parallel-tests-junit
+ powermock
rest-assured
rest-testing
selenium-junit-testng
- spring-testing
spring-testing-2
+ spring-testing
test-containers
testing-assertions
- testng
- junit-5-basics
- easymock
- junit-5-advanced
- xmlunit-2
- junit-4
- testing-libraries
testing-libraries-2
- powermock
+ testing-libraries
+ testng
+ xmlunit-2
zerocode
diff --git a/testing-modules/spring-testing-2/pom.xml b/testing-modules/spring-testing-2/pom.xml
index 4686a20202..40b556732a 100644
--- a/testing-modules/spring-testing-2/pom.xml
+++ b/testing-modules/spring-testing-2/pom.xml
@@ -73,6 +73,5 @@
1.12.2
- 2.21.0
\ No newline at end of file
diff --git a/testing-modules/test-containers/pom.xml b/testing-modules/test-containers/pom.xml
index e83d3aff32..1946b7306f 100644
--- a/testing-modules/test-containers/pom.xml
+++ b/testing-modules/test-containers/pom.xml
@@ -80,17 +80,6 @@
-
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
-
- org.junit.platform
- junit-platform-surefire-provider
- ${junit-platform-surefire-provider.version}
-
-
-
org.codehaus.mojo
exec-maven-plugin
@@ -117,7 +106,7 @@
42.2.6
3.141.59
2.22.2
- 1.3.2
+ 1.3.2