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