From 44a1247a03facd8280022538f6488d6fb56a7cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gargalovi=C4=8D?= <xgargal@fi.muni.cz> Date: Fri, 14 Apr 2023 15:18:45 +0200 Subject: [PATCH] added Exercise Tests --- .../moduleexercise/common/DomainService.java | 5 + .../exercise/ExerciseController.java | 6 + .../exercise/ExerciseFacade.java | 5 + .../exercise/ExerciseRepository.java | 14 + .../exercise/ExerciseService.java | 5 + .../moduleexercise/exercise/ExerciseTest.java | 244 +++++++++++++++--- 6 files changed, 242 insertions(+), 37 deletions(-) diff --git a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/common/DomainService.java b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/common/DomainService.java index ec9d9681..1ce61dc3 100644 --- a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/common/DomainService.java +++ b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/common/DomainService.java @@ -52,4 +52,9 @@ public abstract class DomainService<T extends DomainObject> { public void delete(long id) { getRepository().deleteById(id); } + + public void reset() { + getRepository().deleteAll(); +// getRepository().id/ + } } \ No newline at end of file diff --git a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseController.java b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseController.java index f8d6926a..962d1556 100644 --- a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseController.java +++ b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseController.java @@ -173,4 +173,10 @@ public class ExerciseController { return ResponseEntity.noContent().build(); } +// @TestOnly + @DeleteMapping("/reset") + public void resetTable() { + facade.resetTable(); + } + } diff --git a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseFacade.java b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseFacade.java index 8d9174a5..ef50a6d1 100644 --- a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseFacade.java +++ b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseFacade.java @@ -119,4 +119,9 @@ public class ExerciseFacade { public void delete(long id) { exerciseService.delete(id); } + + public void resetTable() { + exerciseService.reset(); + exerciseService.resetId(); + } } diff --git a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseRepository.java b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseRepository.java index abdc8f01..cd0eba8d 100644 --- a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseRepository.java +++ b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseRepository.java @@ -5,9 +5,11 @@ import org.fuseri.moduleexercise.question.Question; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; /** * A repository interface for managing Exercise entities @@ -30,4 +32,16 @@ public interface ExerciseRepository extends JpaRepository<Exercise, Long> { @Query("SELECT q FROM Exercise e JOIN e.questions q WHERE e.id = :exerciseId") Page<Question> getQuestions(PageRequest pageRequest, @Param("exerciseId") Long exerciseId); + + @Modifying + @Transactional + @Query(value = "TRUNCATE Table exercise",nativeQuery = true) + void resetTable(); + + @Modifying + @Transactional + @Query( value = "ALTER TABLE Exercise ALTER COLUMN id RESTART WITH 1",nativeQuery = true) + void resetId(); + + } diff --git a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseService.java b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseService.java index 6d819b68..4aeed17d 100644 --- a/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseService.java +++ b/application/module-exercise/src/main/java/org/fuseri/moduleexercise/exercise/ExerciseService.java @@ -85,4 +85,9 @@ public class ExerciseService extends DomainService<Exercise> { PageRequest.of(page, DomainService.DEFAULT_PAGE_SIZE), exerciseId); } + + @Transactional + public void resetId() { + repository.resetId(); + } } diff --git a/application/module-exercise/src/test/java/org/fuseri/moduleexercise/exercise/ExerciseTest.java b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/exercise/ExerciseTest.java index 92481d50..796b225e 100644 --- a/application/module-exercise/src/test/java/org/fuseri/moduleexercise/exercise/ExerciseTest.java +++ b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/exercise/ExerciseTest.java @@ -5,20 +5,20 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.fuseri.model.dto.common.Result; import org.fuseri.model.dto.exercise.ExerciseCreateDto; import org.fuseri.model.dto.exercise.ExerciseDto; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; - -import java.util.Map; - +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -38,59 +38,122 @@ public class ExerciseTest { } } + private ExerciseCreateDto exercise1; + private ExerciseCreateDto exercise2; + private ExerciseCreateDto exercise3; - @Test - void getExercise() { - var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, 0L); - - long id = 0L; + @BeforeEach + void init() { + exercise1 = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, 0); + exercise2 = new ExerciseCreateDto("idioms1", "exercise on intermediate idioms", 2, 0); + exercise3 = new ExerciseCreateDto("idioms2", "exercise on basic idioms", 1, 0L); try { - var dis = mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)); - var ok = dis.andReturn().getResponse().getContentAsString(); - - var ll = objectMapper.readValue(ok, ExerciseDto.class); - - id = ll.getId(); + mockMvc.perform(post("/exercises").content(asJsonString(exercise1)).contentType(MediaType.APPLICATION_JSON)); + mockMvc.perform(post("/exercises").content(asJsonString(exercise2)).contentType(MediaType.APPLICATION_JSON)); + mockMvc.perform(post("/exercises").content(asJsonString(exercise3)).contentType(MediaType.APPLICATION_JSON)); } catch (Exception e) { assert (false); } + } + @AfterEach + void cleanup() { + + try { + mockMvc.perform(delete("/exercises/reset")); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + @Test + void getExercise() { + long id = 1L; try { var theId = String.format("/exercises/%s", id); var smth = mockMvc.perform(get(theId)); + smth.andExpect(status().isOk()) + .andExpect(jsonPath("$.name", is(exercise1.getName()))) + .andExpect(jsonPath("$.description", is(exercise1.getDescription()))) + .andExpect(jsonPath("$.courseId", is((int) exercise1.getCourseId()))) + .andExpect(jsonPath("$.difficulty", is(exercise1.getDifficulty()))); + } catch (Exception e) { + //do absolutely nothing + } + } + @Test + void deleteExercise() { + long id = 1L; + try { + var theId = String.format("/exercises/%s", id); + var smth = mockMvc.perform(delete(theId)); + smth.andExpect(status().isNoContent()); } catch (Exception e) { //do absolutely nothing } } @Test - void getFiltered() { + void deleteExercise_notFound() { + long id = 999999L; + try { + var theId = String.format("/exercises/%s", id); + var smth = mockMvc.perform(delete(theId)); + smth.andExpect(status().isNoContent()); + } catch (Exception e) { + //do absolutely nothing + } + } - var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 0, 0L); - var postExercise1 = new ExerciseCreateDto("idioms1", "exercise on basic idioms", 0, 0L); - var postExercise2 = new ExerciseCreateDto("idioms2", "exercise on basic idioms", 1, 0L); + @Test + void getExercise_notFound() { + long id = 999999L; + try { + var theId = String.format("/exercises/%s", id); + var smth = mockMvc.perform(get(theId)); + smth.andExpect(status().isNotFound()); + } catch (Exception e) { + //do absolutely nothing + } + } + + @Test + void FindAll() { try { - var exercise1 = mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)); + var dis = mockMvc.perform(get("/exercises").param("page", "0")); + + dis.andExpect(status().isOk()) + .andExpect(jsonPath("$.total", is(3))) + .andExpect(jsonPath("$.items[0].name", is(exercise1.getName()))) + .andExpect(jsonPath("$.items[0].description", is(exercise1.getDescription()))) + .andExpect(jsonPath("$.items[0].difficulty", is(exercise1.getDifficulty()))) + .andExpect(jsonPath("$.items[0].courseId", is((int) exercise1.getCourseId()))) + .andExpect(jsonPath("$.items[1].name", is(exercise2.getName()))) + .andExpect(jsonPath("$.items[1].description", is(exercise2.getDescription()))) + .andExpect(jsonPath("$.items[1].difficulty", is(exercise2.getDifficulty()))) + .andExpect(jsonPath("$.items[1].courseId", is((int) exercise2.getCourseId()))) + .andExpect(jsonPath("$.items[2].name", is(exercise3.getName()))) + .andExpect(jsonPath("$.items[2].description", is(exercise3.getDescription()))) + .andExpect(jsonPath("$.items[2].difficulty", is(exercise3.getDifficulty()))) + .andExpect(jsonPath("$.items[2].courseId", is((int) exercise3.getCourseId()))); - var exercise2 = mockMvc.perform(post("/exercises").content(asJsonString(postExercise1)).contentType(MediaType.APPLICATION_JSON)); - var exercise3 = mockMvc.perform(post("/exercises").content(asJsonString(postExercise2)).contentType(MediaType.APPLICATION_JSON)); } catch (Exception e) { - //do absolutly nothing + throw new RuntimeException(e); } - Map<String, String> params; + } - try { - var filtered = mockMvc.perform(get("/exercises/filter").param("page", "0").param("courseId", "0").param("difficulty", "0")); + @Test + void getFiltered() { + try { + var filtered = mockMvc.perform(get("/exercises/filter").param("page", "0").param("courseId", "0").param("difficulty", "2")); var content = filtered.andReturn().getResponse().getContentAsString(); - var res = objectMapper.readValue(content, new TypeReference<Result<ExerciseDto>>() { }); @@ -102,11 +165,7 @@ public class ExerciseTest { // @Test // void getByExercise() throws Exception { -// -// var exerciseId = createExercise(); -// var question = createQuestion(exerciseId); -// -// var theId = String.format("/questions/exercise/%s", exerciseId); +// var theId = String.format("/questions/exercise/%s", 9); // // var smth = mockMvc.perform(get(theId).param("page", "0")); // @@ -115,24 +174,94 @@ public class ExerciseTest { // var res = objectMapper.readValue(content, new TypeReference<Result<QuestionDto>>() { // }); // -// Map<String, String> params; // -// assert (res.getItems().get(0).equals(question)); +// +//// assert (res.getItems().get(0).equals(question)); // } @Test void testCreateExercise() throws Exception { - var expectedResponse = new ExerciseDto(); var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, 0L); - mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isCreated()).andExpect(jsonPath("$.name").value("idioms")).andExpect(jsonPath("$.description").value("exercise on basic idioms")).andExpect(jsonPath("$.difficulty").value(2)).andExpect(jsonPath("$.courseId").value("0")).andReturn().getResponse().getContentAsString(); + mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.name").value("idioms")) + .andExpect(jsonPath("$.description").value("exercise on basic idioms")) + .andExpect(jsonPath("$.difficulty").value(2)) + .andExpect(jsonPath("$.courseId").value("0")).andReturn().getResponse().getContentAsString(); } + @Test + void testCreateExerciseEmptyBody() throws Exception { + var postExercise = ""; + + mockMvc.perform(post("/exercises").content((postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()).andReturn().getResponse().getContentAsString(); + } + + + @Test + void testCreateExerciseMissingDesc() throws Exception { + var postExercise = """ + { + "name": "idioms", + "difficulty": 2, + "courseId": 0, + } + """; + + mockMvc.perform(post("/exercises").content((postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()).andReturn().getResponse().getContentAsString(); + } + + @Test + void testCreateExerciseMissingName() throws Exception { + var postExercise = """ + { + "description: "exercise on basic idioms", + "difficulty": 2, + "courseId": 0, + } + """; + + mockMvc.perform(post("/exercises").content((postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()).andReturn().getResponse().getContentAsString(); + } + + @Test + void testCreateExerciseMissingDifficulty() throws Exception { + var postExercise = """ + { + "name": "idioms" + "description: "exercise on basic idioms", + "courseId": 0 + } + """; + + mockMvc.perform(post("/exercises").content((postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()).andReturn().getResponse().getContentAsString(); + } + + @Test + void testCreateExerciseMissingCourseId() throws Exception { + var postExercise = """ + { + "name": "idioms" + "description: "exercise on basic idioms", + "difficulty": 0 + } + """; + + mockMvc.perform(post("/exercises").content((postExercise)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()).andReturn().getResponse().getContentAsString(); + } + + @Test void testUpdate() { var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, 0L); - long id = 0L; + long id = 1L; try { var dis = mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)); @@ -178,4 +307,45 @@ public class ExerciseTest { } + @Test + void testUpdateNotFound() { + long id = 999999L; + var content = """ + { + "name": "idioms", + "description": "exercise on basic idioms", + "difficulty": 2, + "courseId": 0 + } + """; + try { + var theId = String.format("/exercises/%d", id); + mockMvc.perform(put(theId).content(content).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + void testUpdateIncorrectBody() { + long id = 1L; + var content = """ + { + "description": "exercise on basic idioms", + "difficulty": 2, + "courseId": 0 + } + """; + try { + var theId = String.format("/exercises/%d", id); + mockMvc.perform(put(theId).content(content).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } -- GitLab