From 9cb207ae43328db53b0da4c4a3fd8f8eab477349 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 14:01:25 +0100 Subject: [PATCH 1/6] Add category to quiz --- .../ntnu/idatt2105/quizapp/model/quiz/Category.java | 11 ++++++++++- .../edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java | 12 +++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java index 472b935..fa1d664 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java @@ -1,11 +1,15 @@ package edu.ntnu.idatt2105.quizapp.model.quiz; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; @@ -32,10 +36,15 @@ public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") - private long id; + private Long id; @Column(name = "description") private String description; + @OneToMany(mappedBy = "category", cascade = CascadeType.PERSIST) + private List quizzes; + + + } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java index 0f92b1a..c590985 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java @@ -34,11 +34,12 @@ @Getter @Setter @Builder + public class Quiz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "quiz_id") - private long id; + private Long id; @Column(name = "name") private String name; @@ -52,8 +53,13 @@ public class Quiz { @ManyToOne(fetch = FetchType.LAZY) private User author; + @ManyToOne(fetch = FetchType.LAZY) + private Category category; + @Column(name = "open") - private boolean open; + private Boolean isOpen; + + @Override public final boolean equals(Object object) { @@ -73,7 +79,7 @@ public final boolean equals(Object object) { return false; } Quiz quiz = (Quiz) object; - return Objects.equals(getId(), quiz.getId()); + return getId() != null && Objects.equals(getId(), quiz.getId()); } @Override From fbc29819729269d4b4a12c57e71207e358a7fa06 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 14:02:36 +0100 Subject: [PATCH 2/6] Make all class variables of table classes non-primitive --- .../idatt2105/quizapp/dto/quiz/QuizDTO.java | 2 +- .../quizapp/mapper/AnswerMapper.java | 2 +- .../idatt2105/quizapp/mapper/QuizMapper.java | 3 +- .../ntnu/idatt2105/quizapp/model/User.java | 27 ++++++++++++--- .../idatt2105/quizapp/model/quiz/Answer.java | 34 ++++++++++++++++--- .../quizapp/model/quiz/QuizQuestion.java | 6 ++-- .../repositories/quiz/QuizRepository.java | 4 +-- .../quizapp/services/quiz/QuizService.java | 6 ++-- .../quizapp/testdata/QuizTestData.java | 2 +- 9 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/dto/quiz/QuizDTO.java b/src/main/java/edu/ntnu/idatt2105/quizapp/dto/quiz/QuizDTO.java index 088d122..b975eac 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/dto/quiz/QuizDTO.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/dto/quiz/QuizDTO.java @@ -19,5 +19,5 @@ public class QuizDTO { private String description; private List questions; private PublicUserInformationDTO author; - private boolean open; + private boolean isOpen; } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/AnswerMapper.java b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/AnswerMapper.java index 2bcdc03..433d649 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/AnswerMapper.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/AnswerMapper.java @@ -23,7 +23,7 @@ public class AnswerMapper { public AnswerDTO mapToAnswerDTO(Answer answer) { return AnswerDTO.builder() .answerText(answer.getAnswerText()) - .isCorrect(answer.isCorrect()) + .isCorrect(answer.getIsCorrect()) .build(); } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java index b23a47d..f2300b9 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java @@ -52,7 +52,7 @@ public QuizPreviewDTO mapToQuizPreviewDTO(Quiz quiz) { .id(quiz.getId()) .title(quiz.getName()) .description(quiz.getDescription()) - .open(quiz.isOpen()) + .open(quiz.getIsOpen()) .build(); } @@ -71,6 +71,7 @@ public Quiz mapToQuiz(QuizCreationRequestDTO quizCreationRequestDTO, User user) .map(questionMapper::mapToQuizQuestion) .toList()) .author(user) + .isOpen(quizCreationRequestDTO.isOpen()) .build(); createdQuiz.getQuestions().forEach(question -> { diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java index 5235d90..6b64572 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java @@ -1,11 +1,25 @@ package edu.ntnu.idatt2105.quizapp.model; -import jakarta.persistence.*; - +import edu.ntnu.idatt2105.quizapp.model.quiz.Quiz; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import java.util.Collection; import java.util.List; - -import lombok.*; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -17,8 +31,8 @@ * @author Jeffrey Tabiri * @author Ramtin Samavat * @version 1.0 - * @since 2024-03-25 * @see UserDetails + * @since 2024-03-25 */ @Entity @Table(name = "users") @@ -55,6 +69,9 @@ public class User implements UserDetails { @Column(name = "role") private Role role; + @OneToMany(mappedBy = "author", cascade = CascadeType.PERSIST) + private List quizzes; + /** * Retrieves the roles/authorities associated with this user. * diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java index 86320f0..6b7d842 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java @@ -8,12 +8,13 @@ import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import java.util.Objects; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.proxy.HibernateProxy; /** * Model class for Answer. @@ -29,18 +30,43 @@ @Getter @Setter @Builder -@EqualsAndHashCode public class Answer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; + private Long id; private String answerText; - private boolean isCorrect; + private Boolean isCorrect; @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY) private QuizQuestion quizQuestion; + @Override + public final boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null) { + return false; + } + Class oEffectiveClass = object instanceof HibernateProxy ? + ((HibernateProxy) object).getHibernateLazyInitializer() + .getPersistentClass() : object.getClass(); + Class thisEffectiveClass = this instanceof HibernateProxy ? + ((HibernateProxy) this).getHibernateLazyInitializer() + .getPersistentClass() : this.getClass(); + if (thisEffectiveClass != oEffectiveClass) { + return false; + } + Answer answer = (Answer) object; + return getId() != null && Objects.equals(getId(), answer.getId()); + } + @Override + public final int hashCode() { + return this instanceof HibernateProxy ? + ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : + getClass().hashCode(); + } } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java index 7a4eba1..89c6cd9 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java @@ -38,12 +38,12 @@ public class QuizQuestion { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") - private long id; + private Long id; @Column(name = "question_text") private String questionText; - @OneToMany(mappedBy = "quizQuestion", cascade = CascadeType.PERSIST) + @OneToMany(mappedBy = "quizQuestion", cascade = CascadeType.ALL) private List answers; @ManyToOne(fetch = FetchType.LAZY) @@ -67,7 +67,7 @@ public final boolean equals(Object object) { return false; } QuizQuestion that = (QuizQuestion) object; - return Objects.equals(getId(), that.getId()); + return getId() != null && Objects.equals(getId(), that.getId()); } @Override diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/repositories/quiz/QuizRepository.java b/src/main/java/edu/ntnu/idatt2105/quizapp/repositories/quiz/QuizRepository.java index 054c6a6..724f6fb 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/repositories/quiz/QuizRepository.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/repositories/quiz/QuizRepository.java @@ -18,9 +18,9 @@ public interface QuizRepository extends JpaRepository { List findAllByAuthorUsername(String username, Pageable pageable); - List findAllByAuthorUsernameAndOpen(String username, Pageable pageable, boolean open); + List findAllByAuthorUsernameAndIsOpen(String username, Pageable pageable, boolean open); - List findAllByOpen(boolean open, Pageable pageable); + List findAllByIsOpen(boolean open, Pageable pageable); Optional findQuizById(Long id); diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/services/quiz/QuizService.java b/src/main/java/edu/ntnu/idatt2105/quizapp/services/quiz/QuizService.java index e3d3e53..675d60c 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/services/quiz/QuizService.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/services/quiz/QuizService.java @@ -99,7 +99,7 @@ public List getAllQuizPreviewsForUserPaginated(Principal princip */ public List getAllPublicQuizPreviewsForUserPaginated(String username, Pageable pageable) { - return quizRepository.findAllByAuthorUsernameAndOpen(username, pageable, true) + return quizRepository.findAllByAuthorUsernameAndIsOpen(username, pageable, true) .stream() .map(quizMapper::mapToQuizPreviewDTO) .toList(); @@ -112,7 +112,7 @@ public List getAllPublicQuizPreviewsForUserPaginated(String user * @return A list of quiz previews based on the pageable. */ public List browsePublicQuizzesPaginated(Pageable pageable) { - return quizRepository.findAllByOpen(true, pageable) + return quizRepository.findAllByIsOpen(true, pageable) .stream() .map(quizMapper::mapToQuizPreviewDTO) .toList(); @@ -132,7 +132,7 @@ public QuizDTO getQuizById(Principal principal, long id) Quiz quiz = quizRepository.findQuizById(id).orElseThrow(); - if (quiz.isOpen() || quiz.getAuthor().getUsername().equals(principal.getName())) { + if (quiz.getIsOpen() || quiz.getAuthor().getUsername().equals(principal.getName())) { return quizMapper.mapToQuizDTO(quiz); } else { throw new IllegalArgumentException("Principal has no acces to this quiz."); diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/testdata/QuizTestData.java b/src/main/java/edu/ntnu/idatt2105/quizapp/testdata/QuizTestData.java index 9f98fc0..ddb1fb1 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/testdata/QuizTestData.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/testdata/QuizTestData.java @@ -54,7 +54,7 @@ public static void addTestDataToUser(User user, QuizRepository quizRepository) { .name("Example quiz") .description("random desc: " + (randomIntBetween20And30 + i)) .author(user) - .open((i % 2) == 0) + .isOpen((i % 2) == 0) .build(); QuizQuestion quizQuestion = QuizQuestion.builder() From 37ce8e47b7720174879956674987a148e8508f35 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 16:11:09 +0100 Subject: [PATCH 3/6] Add tests to quiz model classes --- .../quizapp/model/quiz/AnswerTest.java | 154 ++++++++++++++++++ .../quizapp/model/quiz/QuizQuestionTest.java | 129 +++++++++++++++ .../quizapp/model/quiz/QuizTest.java | 74 +++++++++ .../quizapp/util/quiz/QuizModelTestUtil.java | 65 ++++++++ 4 files changed, 422 insertions(+) create mode 100644 src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/AnswerTest.java create mode 100644 src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestionTest.java create mode 100644 src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizTest.java create mode 100644 src/test/java/edu/ntnu/idatt2105/quizapp/util/quiz/QuizModelTestUtil.java diff --git a/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/AnswerTest.java b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/AnswerTest.java new file mode 100644 index 0000000..1817d12 --- /dev/null +++ b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/AnswerTest.java @@ -0,0 +1,154 @@ +package edu.ntnu.idatt2105.quizapp.model.quiz; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import edu.ntnu.idatt2105.quizapp.util.quiz.QuizModelTestUtil; +import org.junit.jupiter.api.Test; + + +public class AnswerTest { + + + @Test + public void Equals_EqualAnswers_True() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = QuizModelTestUtil.createAnswerA(); + + //Act + boolean result = answerA.equals(answerB); + + //Assert + assertTrue(result); + } + + @Test + public void Equals_NotEqualAnswers_False() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = QuizModelTestUtil.createAnswerB(); + + //Act + boolean result = answerA.equals(answerB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_Null_False() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = null; + + //Act + boolean result = answerA.equals(answerB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_SameObject_True() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = answerA; + + //Act + boolean result = answerA.equals(answerB); + + //Assert + assertEquals(answerA, answerB); + } + + @Test + public void HashCode_SameObject_True() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = answerA; + + //Act + int hashA = answerA.hashCode(); + int hashB = answerB.hashCode(); + + //Assert + assertEquals(hashA, hashB); + } + + @Test + public void HashCode_EqualObjects_True() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = QuizModelTestUtil.createAnswerA(); + + //Act + int hashA = answerA.hashCode(); + int hashB = answerB.hashCode(); + + //Assert + assertEquals(hashA, hashB); + } + + @Test + public void HashCode_NotEqualObjects_False() { + //Arrange + Answer answerA = QuizModelTestUtil.createAnswerA(); + Answer answerB = QuizModelTestUtil.createAnswerB(); + + //Act + int hashA = answerA.hashCode(); + int hashB = answerB.hashCode(); + + //Assert + assertNotEquals(hashA, hashB); + } + + @Test + public void GetAnswerText_AnswerTextIsHello_Hello() { + //Arrange + Answer answerA = Answer.builder() + .answerText("Hello") + .build(); + String expected = "Hello"; + + //Act + String result = answerA.getAnswerText(); + + + //Assert + assertEquals(result, expected); + } + + @Test + public void GetIsCorrect_IsCorrect_True() { + //Arrange + Answer answerA = new Answer(); + answerA.setIsCorrect(true); + boolean expected = true; + + //Act + boolean result = answerA.getIsCorrect(); + + //Assert + assertEquals(result, expected); + } + + @Test + public void GetId_IdIs1_1() { + //Arrange + Answer answerA = new Answer(); + answerA.setId(1L); + Long expected = 1L; + + //Act + Long result = answerA.getId(); + + //Assert + assertEquals(result, expected); + } + + +} diff --git a/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestionTest.java b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestionTest.java new file mode 100644 index 0000000..2b6a087 --- /dev/null +++ b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestionTest.java @@ -0,0 +1,129 @@ +package edu.ntnu.idatt2105.quizapp.model.quiz; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import edu.ntnu.idatt2105.quizapp.util.quiz.QuizModelTestUtil; +import java.util.List; +import org.junit.jupiter.api.Test; + +/** + * Unit test for the {@link edu.ntnu.idatt2105.quizapp.model.quiz.QuizQuestion} class. + * + * @author Tobias Oftedal + * @version 1.0 + * @since 2024-03-25 + */ +public class QuizQuestionTest { + @Test + public void Equals_EqualQuestions_True() { + //Arrange + QuizQuestion quizQuestionA = QuizModelTestUtil.createQuizQuestionA(); + QuizQuestion quizQuestionB = QuizModelTestUtil.createQuizQuestionA(); + + //Act + boolean result = quizQuestionA.equals(quizQuestionB); + + //Assert + assertTrue(result); + } + + @Test + public void Equals_NotEqualQuestions_False() { + //Arrange + QuizQuestion quizQuestionA = QuizModelTestUtil.createQuizQuestionA(); + QuizQuestion quizQuestionB = QuizModelTestUtil.createQuizQuestionB(); + + //Act + boolean result = quizQuestionA.equals(quizQuestionB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_Null_False() { + //Arrange + QuizQuestion quizQuestionA = QuizModelTestUtil.createQuizQuestionA(); + QuizQuestion quizQuestionB = null; + + //Act + boolean result = quizQuestionA.equals(quizQuestionB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_SameObject_True() { + //Arrange + QuizQuestion quizQuestionA = QuizModelTestUtil.createQuizQuestionA(); + QuizQuestion quizQuestionB = quizQuestionA; + + //Act + boolean result = quizQuestionA.equals(quizQuestionB); + + //Assert + assertTrue(result); + } + + @Test + public void HashCode_SameObject_True() { + //Arrange + QuizQuestion quizQuestionA = QuizModelTestUtil.createQuizQuestionA(); + QuizQuestion quizQuestionB = quizQuestionA; + + //Act + boolean result = quizQuestionA.hashCode() == quizQuestionB.hashCode(); + + //Assert + assertTrue(result); + } + +@Test + public void SetQuestionText_TextIsHello_True() { + //Arrange + QuizQuestion quizQuestion = new QuizQuestion(); + String newQuestionText = "New question text"; + + //Act + quizQuestion.setQuestionText(newQuestionText); + + //Assert + assertNotEquals(QuizModelTestUtil.createQuizQuestionA().getQuestionText(), quizQuestion.getQuestionText()); + } + + @Test + public void SetAnswers_AnswersIsNotEmpty_True() { + //Arrange + QuizQuestion quizQuestion = new QuizQuestion(); + + + Answer answer = QuizModelTestUtil.createAnswerA(); + List answers = List.of(answer); + + + //Act + quizQuestion.setAnswers(answers); + + //Assert + assertEquals(quizQuestion.getAnswers(), answers); + } + + public void SetQuiz_QuizIsNotNull_True() { + //Arrange + QuizQuestion quizQuestion = new QuizQuestion(); + Quiz quiz = QuizModelTestUtil.createQuizA(); + + //Act + quizQuestion.setQuiz(quiz); + + //Assert + assertEquals(quizQuestion.getQuiz(), quiz); + } + + + +} diff --git a/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizTest.java b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizTest.java new file mode 100644 index 0000000..0a5f267 --- /dev/null +++ b/src/test/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizTest.java @@ -0,0 +1,74 @@ +package edu.ntnu.idatt2105.quizapp.model.quiz; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import edu.ntnu.idatt2105.quizapp.util.quiz.QuizModelTestUtil; +import org.junit.jupiter.api.Test; + +public class QuizTest { + @Test + public void Equals_EqualQuizzes_True() { + //Arrange + Quiz quizA = QuizModelTestUtil.createQuizA(); + Quiz quizB = QuizModelTestUtil.createQuizA(); + + //Act + boolean result = quizA.equals(quizB); + + //Assert + assertTrue(result); + } + + @Test + public void Equals_NotEqualQuizzes_False() { + //Arrange + Quiz quizA = QuizModelTestUtil.createQuizA(); + Quiz quizB = QuizModelTestUtil.createQuizB(); + + //Act + boolean result = quizA.equals(quizB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_Null_False() { + //Arrange + Quiz quizA = QuizModelTestUtil.createQuizA(); + Quiz quizB = null; + + //Act + boolean result = quizA.equals(quizB); + + //Assert + assertFalse(result); + } + + @Test + public void Equals_SameObject_True() { + //Arrange + Quiz quizA = QuizModelTestUtil.createQuizA(); + Quiz quizB = quizA; + + //Act + boolean result = quizA.equals(quizB); + + //Assert + assertTrue(result); + } + + @Test + public void Equals_DifferentObject_False() { + //Arrange + Quiz quizA = QuizModelTestUtil.createQuizA(); + Object object = new Object(); + + //Act + boolean result = quizA.equals(object); + + //Assert + assertFalse(result); + } +} diff --git a/src/test/java/edu/ntnu/idatt2105/quizapp/util/quiz/QuizModelTestUtil.java b/src/test/java/edu/ntnu/idatt2105/quizapp/util/quiz/QuizModelTestUtil.java new file mode 100644 index 0000000..ea58444 --- /dev/null +++ b/src/test/java/edu/ntnu/idatt2105/quizapp/util/quiz/QuizModelTestUtil.java @@ -0,0 +1,65 @@ +package edu.ntnu.idatt2105.quizapp.util.quiz; + +import edu.ntnu.idatt2105.quizapp.model.User; +import edu.ntnu.idatt2105.quizapp.model.quiz.Answer; +import edu.ntnu.idatt2105.quizapp.model.quiz.Quiz; +import edu.ntnu.idatt2105.quizapp.model.quiz.QuizQuestion; +import edu.ntnu.idatt2105.quizapp.util.TestUtil; +import java.util.List; + +public class QuizModelTestUtil { + + public static Answer createAnswerA() { + return Answer.builder() + .id(1L) + .answerText("Answer A") + .isCorrect(true) + .build(); + } + + public static Answer createAnswerB() { + return Answer.builder() + .id(2L) + .answerText("Answer B") + .isCorrect(false) + .build(); + } + + public static QuizQuestion createQuizQuestionA() { + return QuizQuestion.builder() + .questionText("Question A") + .answers(List.of(createAnswerA(), createAnswerB())) + .build(); + } + + public static QuizQuestion createQuizQuestionB() { + return QuizQuestion.builder() + .questionText("Question B") + .answers(List.of(createAnswerA(), createAnswerB())) + .build(); + } + + + public static Quiz createQuizA() { + return Quiz.builder() + .id(1L) + .author(TestUtil.createUserA()) + .name("Quiz A") + .description("Description A") + .questions(List.of(createQuizQuestionA(), createQuizQuestionB())) + .isOpen(true) + .build(); + } + public static Quiz createQuizB() { + return Quiz.builder() + .id(2L) + .author(TestUtil.createUserB()) + .name("Quiz B") + .description("Description B") + .questions(List.of(createQuizQuestionA(), createQuizQuestionB())) + .isOpen(true) + .build(); + } + + +} From 4e9b00f0b6066e78afdaa01f54722095efb9f7f1 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 16:11:38 +0100 Subject: [PATCH 4/6] Change equals and hashcode to IntelliJ autogenerated --- .../idatt2105/quizapp/model/quiz/Answer.java | 24 +++++--------- .../quizapp/model/quiz/Category.java | 33 +++++++++++++++---- .../idatt2105/quizapp/model/quiz/Quiz.java | 28 ++++++---------- .../quizapp/model/quiz/QuizQuestion.java | 24 ++++---------- 4 files changed, 51 insertions(+), 58 deletions(-) diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java index 6b7d842..58dac99 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Answer.java @@ -41,31 +41,23 @@ public class Answer { private QuizQuestion quizQuestion; @Override - public final boolean equals(Object object) { + public boolean equals(Object object) { if (this == object) { return true; } - if (object == null) { - return false; - } - Class oEffectiveClass = object instanceof HibernateProxy ? - ((HibernateProxy) object).getHibernateLazyInitializer() - .getPersistentClass() : object.getClass(); - Class thisEffectiveClass = this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer() - .getPersistentClass() : this.getClass(); - if (thisEffectiveClass != oEffectiveClass) { + if (object == null || getClass() != object.getClass()) { return false; } Answer answer = (Answer) object; - return getId() != null && Objects.equals(getId(), answer.getId()); + return Objects.equals(id, answer.id) && + Objects.equals(answerText, answer.answerText) && + Objects.equals(isCorrect, answer.isCorrect) && + Objects.equals(quizQuestion, answer.quizQuestion); } @Override - public final int hashCode() { - return this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : - getClass().hashCode(); + public int hashCode() { + return Objects.hash(id, answerText, isCorrect); } } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java index fa1d664..7b49e6f 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Category.java @@ -10,11 +10,14 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import java.util.List; +import java.util.Objects; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.NonNull; import lombok.Setter; /** @@ -25,26 +28,42 @@ * @since 2024-03-27 */ @Entity -@NoArgsConstructor -@AllArgsConstructor @Table(name = "categories") +@Builder +@AllArgsConstructor +@NoArgsConstructor @Getter @Setter -@Builder -@EqualsAndHashCode public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id") + @Column(name = "id", nullable = false, unique = true) + @NonNull private Long id; - @Column(name = "description") + @Column(name = "description", nullable = false) private String description; @OneToMany(mappedBy = "category", cascade = CascadeType.PERSIST) private List quizzes; + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + Category category = (Category) object; + return Objects.equals(id, category.id) && + Objects.equals(description, category.description) && + Objects.equals(quizzes, category.quizzes); + } - + @Override + public int hashCode() { + return Objects.hash(id, description); + } } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java index c590985..1d1fa02 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/Quiz.java @@ -59,33 +59,25 @@ public class Quiz { @Column(name = "open") private Boolean isOpen; - - @Override - public final boolean equals(Object object) { + public boolean equals(Object object) { if (this == object) { return true; } - if (object == null) { - return false; - } - Class oEffectiveClass = object instanceof HibernateProxy ? - ((HibernateProxy) object).getHibernateLazyInitializer() - .getPersistentClass() : object.getClass(); - Class thisEffectiveClass = this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer() - .getPersistentClass() : this.getClass(); - if (thisEffectiveClass != oEffectiveClass) { + if (object == null || getClass() != object.getClass()) { return false; } Quiz quiz = (Quiz) object; - return getId() != null && Objects.equals(getId(), quiz.getId()); + return Objects.equals(id, quiz.id) && Objects.equals(name, quiz.name) && + Objects.equals(description, quiz.description) && + Objects.equals(questions, quiz.questions) && + Objects.equals(author, quiz.author) && + Objects.equals(category, quiz.category) && + Objects.equals(isOpen, quiz.isOpen); } @Override - public final int hashCode() { - return this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : - getClass().hashCode(); + public int hashCode() { + return Objects.hash(id, name, description, category, isOpen); } } diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java index 89c6cd9..0844500 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/quiz/QuizQuestion.java @@ -17,7 +17,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.proxy.HibernateProxy; /** * Model class for QuizQuestion. @@ -50,30 +49,21 @@ public class QuizQuestion { private Quiz quiz; @Override - public final boolean equals(Object object) { + public boolean equals(Object object) { if (this == object) { return true; } - if (object == null) { - return false; - } - Class oEffectiveClass = object instanceof HibernateProxy ? - ((HibernateProxy) object).getHibernateLazyInitializer() - .getPersistentClass() : object.getClass(); - Class thisEffectiveClass = this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer() - .getPersistentClass() : this.getClass(); - if (thisEffectiveClass != oEffectiveClass) { + if (object == null || getClass() != object.getClass()) { return false; } QuizQuestion that = (QuizQuestion) object; - return getId() != null && Objects.equals(getId(), that.getId()); + return Objects.equals(id, that.id) && + Objects.equals(questionText, that.questionText) && + Objects.equals(answers, that.answers) && Objects.equals(quiz, that.quiz); } @Override - public final int hashCode() { - return this instanceof HibernateProxy ? - ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : - getClass().hashCode(); + public int hashCode() { + return Objects.hash(id, questionText, quiz); } } From 1145cc36ac04a0180223d0f000ec5d6965dbc2b2 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 16:11:49 +0100 Subject: [PATCH 5/6] Add public field to quiz mapper --- src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java index f2300b9..000ef7e 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/mapper/QuizMapper.java @@ -38,6 +38,7 @@ public QuizDTO mapToQuizDTO(Quiz quiz) { .questions(quiz.getQuestions().stream() .map(questionMapper::mapToQuizQuestionDTO) .toList()) + .isOpen(quiz.getIsOpen()) .build(); } From 530a69624c0008c21042e97bdf8eec3664ab6079 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 28 Mar 2024 16:17:30 +0100 Subject: [PATCH 6/6] Change hashcode and equals in User.java --- .../ntnu/idatt2105/quizapp/model/User.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java b/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java index 6b64572..4e088de 100644 --- a/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java +++ b/src/main/java/edu/ntnu/idatt2105/quizapp/model/User.java @@ -13,10 +13,12 @@ import jakarta.persistence.Table; import java.util.Collection; import java.util.List; +import java.util.Objects; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; @@ -37,9 +39,10 @@ @Entity @Table(name = "users") @Builder -@Data @AllArgsConstructor @NoArgsConstructor +@Getter +@Setter public class User implements UserDetails { @Id @@ -111,4 +114,26 @@ public boolean isCredentialsNonExpired() { public boolean isEnabled() { return true; } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + User user = (User) object; + return Objects.equals(userId, user.userId) && + Objects.equals(username, user.username) && + Objects.equals(password, user.password) && + Objects.equals(email, user.email) && Objects.equals(name, user.name) && + Objects.equals(surName, user.surName) && role == user.role && + Objects.equals(quizzes, user.quizzes); + } + + @Override + public int hashCode() { + return Objects.hash(userId, username, password, email, name, surName, role); + } }