diff --git a/pom.xml b/pom.xml
index 6a83d1a..cef314e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,7 +98,7 @@
org.testcontainers
testcontainers-bom
- 1.18.0
+ 1.19.3
pom
import
diff --git a/src/main/java/org/bookstore/dto/book/CreateBookRequestDto.java b/src/main/java/org/bookstore/dto/book/CreateBookRequestDto.java
index 10cf4c8..621ecd0 100644
--- a/src/main/java/org/bookstore/dto/book/CreateBookRequestDto.java
+++ b/src/main/java/org/bookstore/dto/book/CreateBookRequestDto.java
@@ -24,5 +24,6 @@ public record CreateBookRequestDto(
String description,
@Size(max = 255, message = "Maximum allowed size 255 characters")
String coverImage,
+ @NotNull
Set categoryIds) {
}
diff --git a/src/test/java/org/bookstore/controller/BookControllerTest.java b/src/test/java/org/bookstore/controller/BookControllerTest.java
index 38dbc8b..070d5ed 100644
--- a/src/test/java/org/bookstore/controller/BookControllerTest.java
+++ b/src/test/java/org/bookstore/controller/BookControllerTest.java
@@ -60,7 +60,7 @@ static void beforeAll(@Autowired WebApplicationContext applicationContext) {
"classpath:/scripts/books/delete-books.sql",
"classpath:/scripts/categories/create-categories.sql"
})
- @WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
+ @WithMockUser(username = "admin", authorities = {"ADMIN"})
void createBook_validRequestDto_returnsDto() throws Exception {
CreateBookRequestDto request = new CreateBookRequestDto(
"title",
@@ -73,7 +73,7 @@ void createBook_validRequestDto_returnsDto() throws Exception {
);
MvcResult result = mockMvc.perform(post("/books")
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andReturn();
@@ -151,7 +151,7 @@ void updateBookById_existingBook_BookDto() throws Exception {
);
MvcResult result = mockMvc.perform(put("/books/" + id)
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
@@ -166,11 +166,34 @@ void updateBookById_existingBook_BookDto() throws Exception {
.hasFieldOrPropertyWithValue("coverImage", "image_changed");
}
+ @Test
+ @DisplayName("Create book with invalid request dto")
+ @Sql(scripts = {
+ "classpath:/scripts/books/delete-books.sql",
+ })
+ @WithMockUser(username = "admin", authorities = {"ADMIN"})
+ void createBook_invalidRequestDto_Exception() throws Exception {
+ CreateBookRequestDto request = new CreateBookRequestDto(
+ "title",
+ "author",
+ "12345678900",
+ BigDecimal.valueOf(-100),
+ "descr",
+ "image",
+ Set.of(1L)
+ );
+
+ mockMvc.perform(post("/books")
+ .content(objectMapper.writeValueAsString(request))
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isBadRequest());
+ }
+
@Test
@DisplayName("Update non-existing book")
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
@Sql(scripts = "classpath:/scripts/books/delete-books.sql")
- void updateBookById_nonExistingBook_exception() throws Exception {
+ void updateBookById_nonExistingBook_Exception() throws Exception {
long id = 1;
CreateBookRequestDto request = new CreateBookRequestDto(
"title",
@@ -183,10 +206,9 @@ void updateBookById_nonExistingBook_exception() throws Exception {
);
mockMvc.perform(put("/books/" + id)
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
@Test
@@ -194,8 +216,7 @@ void updateBookById_nonExistingBook_exception() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void deleteById_existingBook_Ok() throws Exception {
mockMvc.perform(delete("/books/1"))
- .andExpect(status().isNoContent())
- .andReturn();
+ .andExpect(status().isNoContent());
}
@Test
@@ -203,8 +224,7 @@ void deleteById_existingBook_Ok() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void findById_nonExistingBook_Exception() throws Exception {
mockMvc.perform(get("/books/100"))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
@Test
@@ -223,11 +243,9 @@ void updateById_nonExistingBook_Exception() throws Exception {
);
mockMvc.perform(put("/books/" + id)
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
- .andExpect(status().isNotFound())
- .andReturn();
-
+ .andExpect(status().isNotFound());
}
@Test
@@ -235,7 +253,6 @@ void updateById_nonExistingBook_Exception() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void deleteById_nonExistingBook_Exception() throws Exception {
mockMvc.perform(delete("/books/100"))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
}
diff --git a/src/test/java/org/bookstore/controller/CategoryControllerTest.java b/src/test/java/org/bookstore/controller/CategoryControllerTest.java
index 9c52657..9174e3e 100644
--- a/src/test/java/org/bookstore/controller/CategoryControllerTest.java
+++ b/src/test/java/org/bookstore/controller/CategoryControllerTest.java
@@ -59,7 +59,7 @@ void createCategory_validDto_CategoryDto() throws Exception {
);
MvcResult result = mockMvc.perform(post("/categories")
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
@@ -122,7 +122,7 @@ void updateCategory_validDto_CategoryDto() throws Exception {
"some new scary text"
);
MvcResult result = mockMvc.perform(put("/categories/" + id)
- .content(objectMapper.writeValueAsBytes(updateRequest))
+ .content(objectMapper.writeValueAsString(updateRequest))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
@@ -142,8 +142,7 @@ void updateCategory_validDto_CategoryDto() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void deleteById_existingBook_Ok() throws Exception {
mockMvc.perform(delete("/categories/1"))
- .andExpect(status().isOk())
- .andReturn();
+ .andExpect(status().isOk());
}
@Test
@@ -151,8 +150,7 @@ void deleteById_existingBook_Ok() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void findById_nonExistingCategory_Exception() throws Exception {
mockMvc.perform(get("/categories/100"))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
@Test
@@ -166,10 +164,9 @@ void updateById_nonExistingCategory_Exception() throws Exception {
);
mockMvc.perform(put("/categories/" + id)
- .content(objectMapper.writeValueAsBytes(request))
+ .content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
@Test
@@ -177,7 +174,6 @@ void updateById_nonExistingCategory_Exception() throws Exception {
@WithMockUser(username = "admin", authorities = {"USER", "ADMIN"})
void deleteById_nonExistingCategory_Exception() throws Exception {
mockMvc.perform(delete("/categories/100"))
- .andExpect(status().isNotFound())
- .andReturn();
+ .andExpect(status().isNotFound());
}
}
diff --git a/src/test/java/org/bookstore/service/BookServiceTest.java b/src/test/java/org/bookstore/service/BookServiceTest.java
index 2ec7d73..ab441c7 100644
--- a/src/test/java/org/bookstore/service/BookServiceTest.java
+++ b/src/test/java/org/bookstore/service/BookServiceTest.java
@@ -1,12 +1,15 @@
package org.bookstore.service;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
+import java.util.Optional;
import java.util.Set;
import org.bookstore.dto.book.BookDto;
import org.bookstore.dto.book.CreateBookRequestDto;
+import org.bookstore.exceptions.EntityNotFoundException;
import org.bookstore.mapper.BookMapper;
import org.bookstore.mapper.impl.BookMapperImpl;
import org.bookstore.model.Book;
@@ -37,22 +40,13 @@ public class BookServiceTest {
private BookServiceImpl bookService;
@Test
- @DisplayName("Save new book")
- void saveBook_validBookDto_BookDto() {
+ @DisplayName("Save valid book")
+ void save_validRequestDto_BookDto() {
Category category = new Category();
category.setId(1L);
category.setName("name");
category.setDescription("desc");
- Book book = new Book();
- book.setAuthor("author");
- book.setTitle("title");
- book.setCategories(Set.of(category));
- book.setIsbn("isbn-000001");
- book.setPrice(BigDecimal.TEN);
- book.setDescription("descr");
- book.setCoverImage("image");
-
CreateBookRequestDto request = new CreateBookRequestDto(
"title",
"author",
@@ -63,6 +57,15 @@ void saveBook_validBookDto_BookDto() {
Set.of(1L)
);
+ Book book = new Book();
+ book.setAuthor(request.author());
+ book.setTitle(request.title());
+ book.setCategories(Set.of(category));
+ book.setIsbn(request.isbn());
+ book.setPrice(request.price());
+ book.setDescription(request.description());
+ book.setCoverImage(request.coverImage());
+
when(bookRepository.save(book)).thenReturn(book);
when(bookMapper.toEntity(request)).thenReturn(book);
when(categoryRepository.getReferenceById(1L)).thenReturn(category);
@@ -76,4 +79,80 @@ void saveBook_validBookDto_BookDto() {
.hasFieldOrPropertyWithValue("coverImage", request.coverImage())
.hasFieldOrPropertyWithValue("categoriesIds", request.categoryIds());
}
+
+ @Test
+ @DisplayName("Get book with valid id")
+ void getBookById_validId_BookDto() {
+ Book book = new Book();
+ book.setId(1L);
+ book.setAuthor("Author");
+ book.setTitle("Title");
+ book.setIsbn("553322");
+ book.setPrice(BigDecimal.valueOf(125.55));
+ book.setDescription("some desc");
+ book.setCoverImage("some url");
+
+ when(bookRepository.findById(1L)).thenReturn(Optional.of(book));
+
+ BookDto actual = bookService.findById(1L);
+
+ assertThat(actual)
+ .hasFieldOrPropertyWithValue("id", book.getId())
+ .hasFieldOrPropertyWithValue("title", book.getTitle())
+ .hasFieldOrPropertyWithValue("author", book.getAuthor())
+ .hasFieldOrPropertyWithValue("price", book.getPrice())
+ .hasFieldOrPropertyWithValue("description", book.getDescription())
+ .hasFieldOrPropertyWithValue("coverImage", book.getCoverImage());
+ }
+
+ @Test
+ @DisplayName("Get book with not existing id")
+ void getBookById_notValidId_Exception() {
+ Long id = 100L;
+ when(bookRepository.findById(id)).thenReturn(Optional.empty());
+
+ assertThatThrownBy(() -> bookService.findById(id))
+ .isInstanceOf(EntityNotFoundException.class);
+ }
+
+ @Test
+ @DisplayName("Update existing book with valid request")
+ void updateBook_validRequestDto_BookDto() {
+ Long id = 1L;
+ CreateBookRequestDto requestDto = new CreateBookRequestDto(
+ "Title",
+ "Author",
+ "553322",
+ BigDecimal.valueOf(125.55),
+ "some desc",
+ "some url",
+ Set.of(id));
+
+ Category category = new Category();
+ category.setId(id);
+
+ Book book = new Book();
+ book.setId(id);
+ book.setAuthor(requestDto.author());
+ book.setTitle(requestDto.title());
+ book.setIsbn(requestDto.isbn());
+ book.setPrice(requestDto.price());
+ book.setDescription(requestDto.description());
+ book.setCoverImage(requestDto.coverImage());
+ book.setCategories(Set.of(category));
+
+ when(bookRepository.findById(id)).thenReturn(Optional.of(book));
+ when(bookRepository.save(book)).thenReturn(book);
+
+ BookDto actual = bookService.updateBookById(id, requestDto);
+
+ assertThat(actual)
+ .hasFieldOrPropertyWithValue("id", id)
+ .hasFieldOrPropertyWithValue("title", requestDto.title())
+ .hasFieldOrPropertyWithValue("author", requestDto.author())
+ .hasFieldOrPropertyWithValue("price", requestDto.price())
+ .hasFieldOrPropertyWithValue("description", requestDto.description())
+ .hasFieldOrPropertyWithValue("coverImage", requestDto.coverImage())
+ .hasFieldOrPropertyWithValue("categoriesIds", requestDto.categoryIds());
+ }
}
diff --git a/src/test/java/org/bookstore/service/CategoryServiceTest.java b/src/test/java/org/bookstore/service/CategoryServiceTest.java
index 18ade97..2cbb368 100644
--- a/src/test/java/org/bookstore/service/CategoryServiceTest.java
+++ b/src/test/java/org/bookstore/service/CategoryServiceTest.java
@@ -1,10 +1,13 @@
package org.bookstore.service;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;
+import java.util.Optional;
import org.bookstore.dto.category.CategoryDto;
import org.bookstore.dto.category.CreateCategoryRequestDto;
+import org.bookstore.exceptions.EntityNotFoundException;
import org.bookstore.mapper.CategoryMapper;
import org.bookstore.mapper.impl.CategoryMapperImpl;
import org.bookstore.model.Category;
@@ -22,29 +25,93 @@
public class CategoryServiceTest {
@Spy
private CategoryMapper categoryMapper = new CategoryMapperImpl();
-
@Mock
private CategoryRepository categoryRepository;
@InjectMocks
private CategoryServiceImpl categoryService;
@Test
- @DisplayName("Save new category")
- void saveCategory_validCategoryDto_CategoryDto() {
- Category category = new Category();
- category.setDescription("descr");
- category.setName("name");
-
- CreateCategoryRequestDto request = new CreateCategoryRequestDto(
+ @DisplayName("Save new category with valid request")
+ void save_validRequestDto_CategoryDto() {
+ CreateCategoryRequestDto requestDto = new CreateCategoryRequestDto(
"name",
- "descr"
+ "some desc"
);
+ Category category = new Category();
+ category.setName(requestDto.name());
+ category.setDescription(requestDto.description());
+
when(categoryRepository.save(category)).thenReturn(category);
- when(categoryMapper.toEntity(request)).thenReturn(category);
- CategoryDto dto = categoryService.save(request);
- assertThat(dto)
- .hasFieldOrPropertyWithValue("name", request.name())
- .hasFieldOrPropertyWithValue("description", request.description());
+
+ CategoryDto actual = categoryService.save(requestDto);
+ assertThat(actual)
+ .hasFieldOrPropertyWithValue("name", requestDto.name())
+ .hasFieldOrPropertyWithValue("description", requestDto.description());
+ }
+
+ @Test
+ @DisplayName("Update existing category with valid request")
+ void update_validRequestDto_CategoryDto() {
+ Category category = new Category();
+ category.setName("name1");
+ category.setDescription("desc1");
+ category.setId(1L);
+
+ CreateCategoryRequestDto requestDto = new CreateCategoryRequestDto("name2", "desc2");
+
+ Category requestCategory = new Category();
+ requestCategory.setId(1L);
+ requestCategory.setName(requestDto.name());
+ requestCategory.setDescription(requestDto.description());
+
+ when(categoryRepository.findById(1L)).thenReturn(Optional.of(category));
+ when(categoryRepository.save(category)).thenReturn(requestCategory);
+
+ CategoryDto actual = categoryService.update(1L, requestDto);
+
+ assertThat(actual)
+ .hasFieldOrPropertyWithValue("name", "name2")
+ .hasFieldOrPropertyWithValue("description", "desc2");
+ }
+
+ @Test
+ @DisplayName("Update not existing category")
+ void update_notValidRequestDto_Exception() {
+ Long id = 100L;
+ CreateCategoryRequestDto requestDto = new CreateCategoryRequestDto(
+ "name",
+ "desc");
+
+ when(categoryRepository.findById(id)).thenReturn(Optional.empty());
+ assertThatThrownBy(() -> categoryService.update(id, requestDto))
+ .isInstanceOf(EntityNotFoundException.class);
+ }
+
+ @Test
+ @DisplayName("Get category by valid id")
+ void getById_validId_CategoryDto() {
+ Category category = new Category();
+ category.setName("name");
+ category.setDescription("desc");
+ category.setId(1L);
+
+ when(categoryRepository.findById(1L)).thenReturn(Optional.of(category));
+
+ CategoryDto actual = categoryService.getById(1L);
+
+ assertThat(actual)
+ .hasFieldOrPropertyWithValue("name", "name")
+ .hasFieldOrPropertyWithValue("description", "desc");
+ }
+
+ @Test
+ @DisplayName("Get category by not existing id")
+ void getById_notValidId_Exception() {
+ Long id = 100L;
+ when(categoryRepository.findById(id)).thenReturn(Optional.empty());
+
+ assertThatThrownBy(() -> categoryService.getById(id))
+ .isInstanceOf(EntityNotFoundException.class);
}
}