diff --git a/application/model/src/main/java/org/fuseri/model/dto/exercise/AnswerDto.java b/application/model/src/main/java/org/fuseri/model/dto/exercise/AnswerDto.java
index 632cf5c472ffc75689a33ead0ccecdd718d96b35..433244900c287f01549b3e43a4971f68a86a2cc7 100644
--- a/application/model/src/main/java/org/fuseri/model/dto/exercise/AnswerDto.java
+++ b/application/model/src/main/java/org/fuseri/model/dto/exercise/AnswerDto.java
@@ -6,6 +6,8 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.fuseri.model.dto.common.DomainObjectDto;
 
+import java.util.Objects;
+
 @AllArgsConstructor
 @Getter
 public class AnswerDto extends DomainObjectDto {
@@ -15,4 +17,22 @@ public class AnswerDto extends DomainObjectDto {
 
     @NotNull
     private boolean correct;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        AnswerDto answerDto = (AnswerDto) o;
+
+        if (correct != answerDto.correct) return false;
+        return Objects.equals(text, answerDto.text);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = text != null ? text.hashCode() : 0;
+        result = 31 * result + (correct ? 1 : 0);
+        return result;
+    }
 }
diff --git a/application/model/src/main/java/org/fuseri/model/dto/exercise/ExerciseDto.java b/application/model/src/main/java/org/fuseri/model/dto/exercise/ExerciseDto.java
index 250c3025478d0b155b8e0013e6ac58ac16ea9402..ff7abd444839ba89d15b50e72f31a3973b62ceef 100644
--- a/application/model/src/main/java/org/fuseri/model/dto/exercise/ExerciseDto.java
+++ b/application/model/src/main/java/org/fuseri/model/dto/exercise/ExerciseDto.java
@@ -7,6 +7,8 @@ import lombok.Getter;
 import lombok.Setter;
 import org.fuseri.model.dto.common.DomainObjectDto;
 
+import java.util.Objects;
+
 @Getter
 @Setter
 public class ExerciseDto extends DomainObjectDto {
@@ -23,4 +25,26 @@ public class ExerciseDto extends DomainObjectDto {
 
     @NotBlank
     private String courseId;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ExerciseDto that = (ExerciseDto) o;
+
+        if (difficulty != that.difficulty) return false;
+        if (!Objects.equals(name, that.name)) return false;
+        if (!Objects.equals(description, that.description)) return false;
+        return Objects.equals(courseId, that.courseId);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (description != null ? description.hashCode() : 0);
+        result = 31 * result + difficulty;
+        result = 31 * result + (courseId != null ? courseId.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/application/model/src/main/java/org/fuseri/model/dto/exercise/QuestionDto.java b/application/model/src/main/java/org/fuseri/model/dto/exercise/QuestionDto.java
index 6aa390931227ecb391227689ed1451c5f226aa7e..5cca20b14b60c9361eaea0893ff874500b690c61 100644
--- a/application/model/src/main/java/org/fuseri/model/dto/exercise/QuestionDto.java
+++ b/application/model/src/main/java/org/fuseri/model/dto/exercise/QuestionDto.java
@@ -7,6 +7,7 @@ import lombok.Setter;
 import org.fuseri.model.dto.common.DomainObjectDto;
 
 import java.util.List;
+import java.util.Objects;
 
 @Getter
 @Setter
@@ -20,4 +21,24 @@ public class QuestionDto extends DomainObjectDto {
 
     @Valid
     private List<AnswerDto> answers;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        QuestionDto that = (QuestionDto) o;
+
+        if (!Objects.equals(text, that.text)) return false;
+        if (!Objects.equals(exerciseId, that.exerciseId)) return false;
+        return Objects.equals(answers, that.answers);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = text != null ? text.hashCode() : 0;
+        result = 31 * result + (exerciseId != null ? exerciseId.hashCode() : 0);
+        result = 31 * result + (answers != null ? answers.hashCode() : 0);
+        return result;
+    }
 }
diff --git a/application/module-exercise/src/test/java/org/fuseri/moduleexercise/answer/AnswerTest.java b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/answer/AnswerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3fd9e3e3a438386b2f2723edaef20b84b1c9db3
--- /dev/null
+++ b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/answer/AnswerTest.java
@@ -0,0 +1,173 @@
+package org.fuseri.moduleexercise.answer;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.fuseri.model.dto.exercise.AnswerDto;
+import org.fuseri.model.dto.exercise.AnswerInQuestionCreateDto;
+import org.fuseri.model.dto.exercise.AnswersCreateDto;
+import org.fuseri.model.dto.exercise.ExerciseCreateDto;
+import org.fuseri.model.dto.exercise.ExerciseDto;
+import org.fuseri.model.dto.exercise.QuestionCreateDto;
+import org.fuseri.model.dto.exercise.QuestionDto;
+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.List;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+public class AnswerTest {
+
+    @Autowired
+    ObjectMapper objectMapper;
+    @Autowired
+    private MockMvc mockMvc;
+
+    public static String asJsonString(final Object obj) {
+        try {
+            return new ObjectMapper().writeValueAsString(obj);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private QuestionDto createQuestion(String id) throws Exception {
+        var question = new QuestionCreateDto("this statement is false", id,
+                List.of(new AnswerInQuestionCreateDto("dis a logical paradox", true)));
+
+
+        var posted = mockMvc.perform(post("/questions")
+                .content(asJsonString(question))
+                .contentType(MediaType.APPLICATION_JSON));
+
+        var cont = posted.andReturn().getResponse().getContentAsString();
+        var res = objectMapper.readValue(cont, QuestionDto.class);
+        return res;
+    }
+
+
+    private String createExercise() {
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, "0");
+
+        String id = "";
+
+        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();
+        } catch (Exception e) {
+            assert (false);
+        }
+        return id;
+    }
+
+
+    @Test
+    void testCreateAnswer() throws Exception {
+
+        List<AnswerDto> res = createAnswr();
+
+        var expected1 = new AnswerDto("True", false);
+        var expected2 = new AnswerDto("False", false);
+
+        assert (res.get(0).equals(expected1));
+        assert (res.get(1).equals(expected2));
+
+    }
+
+    private List<AnswerDto> createAnswr() throws Exception {
+        var exerciseId = createExercise();
+        var question = createQuestion(exerciseId);
+
+        var incorrect1 = new AnswerInQuestionCreateDto("True", false);
+        var incorrect2 = new AnswerInQuestionCreateDto("False", false);
+
+        var createAnswer = new AnswersCreateDto(question.getId(), List.of(incorrect1, incorrect2));
+
+        var posted = mockMvc.perform(post("/answers")
+                .content(asJsonString(createAnswer))
+                .contentType(MediaType.APPLICATION_JSON));
+
+        var asStr = posted.andReturn().getResponse().getContentAsString();
+
+        var res = objectMapper.readValue(asStr, new TypeReference<List<AnswerDto>>() {
+        });
+        return res;
+    }
+
+
+    @Test
+    void getAnswer() throws Exception {
+        var exerciseId = createExercise();
+        var question = createQuestion(exerciseId);
+
+        var gets = mockMvc.perform(get(String.format("/answers/%s", question.getId())));
+
+        var content2 = gets.andReturn().getResponse().getContentAsString();
+
+        var res = objectMapper.readValue(content2, new TypeReference<List<AnswerDto>>() {
+        });
+
+        assert (res.equals(question.getAnswers()));
+
+    }
+
+    @Test
+    void TestUpdate() throws Exception {
+
+        var exerciseId = createExercise();
+        var question = createQuestion(exerciseId);
+
+        var incorrect1 = new AnswerInQuestionCreateDto("True", false);
+        var incorrect2 = new AnswerInQuestionCreateDto("False", false);
+
+
+        var createAnswer = new AnswersCreateDto(question.getId(), List.of(incorrect1, incorrect2));
+
+
+        var posted = mockMvc.perform(post("/answers")
+                .content(asJsonString(createAnswer))
+                .contentType(MediaType.APPLICATION_JSON));
+
+        var asStr = posted.andReturn().getResponse().getContentAsString();
+
+        var res = objectMapper.readValue(asStr, new TypeReference<List<AnswerDto>>() {
+        });
+
+
+        var updated = """
+                {
+                  "text": "dis true",
+                  "correct": false,
+                  "questionId": "%s"
+                }
+                """;
+
+
+        updated = String.format(updated, question.getId());
+
+        var puts = mockMvc.perform(put(String.format("/answers/%s", res.get(0).getId()))
+                .content(updated).contentType(MediaType.APPLICATION_JSON));
+
+        var content = puts.andReturn().getResponse().getContentAsString();
+
+        var res2 = objectMapper.readValue(content, AnswerDto.class);
+
+        var expected = new AnswerDto("dis true", false);
+
+        assert res2.equals(expected);
+
+    }
+
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..00902bdcd8cbd8850552443d7d727cd500fe7a4a
--- /dev/null
+++ b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/exercise/ExerciseTest.java
@@ -0,0 +1,161 @@
+package org.fuseri.moduleexercise.exercise;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+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.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.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;
+
+
+@SpringBootTest
+@AutoConfigureMockMvc
+public class ExerciseTest {
+    @Autowired
+    ObjectMapper objectMapper;
+    @Autowired
+    private MockMvc mockMvc;
+
+    public static String asJsonString(final Object obj) {
+        try {
+            return new ObjectMapper().writeValueAsString(obj);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    @Test
+    void getExercise() {
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, "0");
+
+        String id = "";
+
+        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();
+        } catch (Exception e) {
+            assert (false);
+        }
+
+
+        try {
+            var theId = String.format("/exercises/%s", id);
+            var smth = mockMvc.perform(get(theId));
+
+        } catch (Exception e) {
+            //do absolutely nothing
+        }
+    }
+
+    @Test
+    void getFiltered() {
+
+
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 0, "0");
+        var postExercise1 = new ExerciseCreateDto("idioms1", "exercise on basic idioms", 0, "0");
+        var postExercise2 = new ExerciseCreateDto("idioms2", "exercise on basic idioms", 1, "0");
+
+        try {
+            var exercise1 = mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON));
+
+            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
+        }
+
+
+        Map<String, String> params;
+
+        try {
+            var filtered = mockMvc.perform(get("/exercises/filter").param("page", "0").param("courseId", "0").param("difficulty", "0"));
+
+            var content = filtered.andReturn().getResponse().getContentAsString();
+
+            var res = objectMapper.readValue(content, new TypeReference<Result<ExerciseDto>>() {
+            });
+
+            assert (res.getTotal() == 2);
+        } catch (Exception e) {
+            assert (false);
+        }
+    }
+
+    @Test
+    void testCreateExercise() throws Exception {
+        var expectedResponse = new ExerciseDto();
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, "0");
+
+        mockMvc.perform(post("/exercises").content(asJsonString(postExercise)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).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 TestUpdate() {
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, "0");
+
+        String id = "";
+
+        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();
+        } catch (Exception e) {
+            assert (false);
+        }
+
+        var expectedExercise = new ExerciseDto();
+        expectedExercise.setId(id);
+        expectedExercise.setName("idioms");
+        expectedExercise.setDifficulty(2);
+        expectedExercise.setCourseId("idioms");
+        expectedExercise.setDescription("exercise on basic idioms");
+
+        var content = """
+                {
+                  "name": "idioms",
+                  "description": "exercise on basic idioms",
+                  "difficulty": 2,
+                  "courseId": "idioms"
+                }
+                """;
+
+
+        try {
+            var theId = String.format("/exercises/%s", id);
+            var dis = mockMvc.perform(put(theId).content(content).contentType(MediaType.APPLICATION_JSON));
+
+            var str = dis.andReturn().getResponse().getContentAsString();
+
+            var res = objectMapper.readValue(str, ExerciseDto.class);
+
+            assert res.equals(expectedExercise);
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+}
diff --git a/application/module-exercise/src/test/java/org/fuseri/moduleexercise/question/QuestionTest.java b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/question/QuestionTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a099ff7c8cf058e033931222d5c76469ac40003e
--- /dev/null
+++ b/application/module-exercise/src/test/java/org/fuseri/moduleexercise/question/QuestionTest.java
@@ -0,0 +1,153 @@
+package org.fuseri.moduleexercise.question;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.fuseri.model.dto.common.Result;
+import org.fuseri.model.dto.exercise.AnswerDto;
+import org.fuseri.model.dto.exercise.AnswerInQuestionCreateDto;
+import org.fuseri.model.dto.exercise.ExerciseCreateDto;
+import org.fuseri.model.dto.exercise.ExerciseDto;
+import org.fuseri.model.dto.exercise.QuestionCreateDto;
+import org.fuseri.model.dto.exercise.QuestionDto;
+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.List;
+import java.util.Map;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+
+
+@SpringBootTest
+@AutoConfigureMockMvc
+public class QuestionTest {
+
+    @Autowired
+    ObjectMapper objectMapper;
+    @Autowired
+    private MockMvc mockMvc;
+
+    public static String asJsonString(final Object obj) {
+        try {
+            return new ObjectMapper().writeValueAsString(obj);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    void testCreateQuestion() throws Exception {
+        String id = createExercise();
+        var answr = new AnswerDto("dis a logical paradox", true);
+        QuestionDto res = createQuestion(id);
+        var expected = new QuestionDto();
+        expected.setAnswers(List.of(answr));
+        expected.setExerciseId(id);
+        expected.setId(res.getId());
+        expected.setText("this statement is false");
+
+        assert expected.equals(res);
+    }
+
+    private QuestionDto createQuestion(String id) throws Exception {
+        var question = new QuestionCreateDto("this statement is false", id, List.of(new AnswerInQuestionCreateDto("dis a logical paradox", true)));
+
+
+        var posted = mockMvc.perform(post("/questions").content(asJsonString(question)).contentType(MediaType.APPLICATION_JSON));
+
+
+        var cont = posted.andReturn().getResponse().getContentAsString();
+        var res = objectMapper.readValue(cont, QuestionDto.class);
+        return res;
+    }
+
+    private String createExercise() {
+        var postExercise = new ExerciseCreateDto("idioms", "exercise on basic idioms", 2, "0");
+
+        String id = "";
+
+        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();
+        } catch (Exception e) {
+            assert (false);
+        }
+        return id;
+    }
+
+
+    @Test
+    void getQuestion() throws Exception {
+
+
+        String exerciseId = createExercise();
+        var question = createQuestion(exerciseId);
+
+        var theId = String.format("/questions/%s", question.getId());
+
+
+        var gets = mockMvc.perform(get(theId));
+
+        var content = gets.andReturn().getResponse().getContentAsString();
+        var res = objectMapper.readValue(content, QuestionDto.class);
+
+        assert res.equals(question);
+
+    }
+
+    @Test
+    void getByExercise() throws Exception {
+
+        var exerciseId = createExercise();
+        var question = createQuestion(exerciseId);
+
+        var theId = String.format("/questions/exercise/%s", exerciseId);
+
+        var smth = mockMvc.perform(get(theId).param("page", "0"));
+
+        var content = smth.andReturn().getResponse().getContentAsString();
+
+        var res = objectMapper.readValue(content, new TypeReference<Result<QuestionDto>>() {
+        });
+
+        Map<String, String> params;
+
+        assert (res.getItems().get(0).equals(question));
+    }
+
+    @Test
+    void TestUpdate() throws Exception {
+        String id = createExercise();
+        var question = createQuestion(id);
+
+        var updated = """
+                {
+                  "text": "wat a paradox?",
+                  "exerciseId": "%s"
+                }
+                """;
+
+        updated = String.format(updated, id);
+
+        var smth = mockMvc.perform(put(String.format("/questions/%s", question.getId())).content(updated).contentType(MediaType.APPLICATION_JSON));
+
+        var content = smth.andReturn().getResponse().getContentAsString();
+
+        var res = objectMapper.readValue(content, QuestionDto.class);
+
+        question.setText("wat a paradox?");
+
+        assert (question.equals(res));
+
+    }
+}