Activitats

Un usuari només ha de respondre un cop a una pregunta

L’objectiu d’aquesta activitat és canviar la implementació de QuestionService per tal que un usuari només pugui contestar un cop una pregunta.

A partir del següent

codi ( 30.3 KB )
, modifiqueu QuestionService afegint el mètode hasUserAnsweredTheQuestion i afegiu la seva implementació a QuestionServiceImpl.

Creeu també un nou mètode UserDAO.findAnswers que retorni totes les respostes d’un usuari i utilitzeu-lo a la implementació de hasUserAnsweredTheQuestion.

  1. public Boolean hasUserAnsweredTheQuestion(Integer questionId, Integer userId);

  1. public interface UserDAO {
  2. public Set<Answer> findAnswers(Integer userId);
  3. }
  4.  
  5. @Repository("userHibernateDAO")
  6. @Transactional
  7. public class UserHibernateDAO implements UserDAO {
  8. @Override
  9. public Set<Answer> findAnswers(Integer userId){
  10. User user = getById(userId);
  11. return user.getAnswers();
  12. }
  13. }
  14.  
  15. @Transactional
  16. public class QuestionServiceImpl implements QuestionService {
  17.  
  18. @Override
  19. public Question addAnswer(Answer answer, Integer questionId, Integer userId) {
  20. Question question = questionDAO.getById(questionId);
  21. if(!hasUserAnsweredTheQuestion(questionId, userId)){
  22. User user = userDAO.getById(userId);
  23. Set<Answer> userAnswers = user.getAnswers();
  24. addAnswerToCollection(answer, userAnswers);
  25. user.setAnswers(userAnswers);
  26. userDAO.save(user);
  27.  
  28.  
  29. Set<Answer> answers = question.getAnswers();
  30. answers = addAnswerToCollection(answer, answers);
  31. question.setAnswers(answers);
  32. questionDAO.update(question);
  33. }
  34. return question;
  35. }
  36.  
  37. @Override
  38. public Boolean hasUserAnsweredTheQuestion(Integer questionId, Integer userId) {
  39. Question question = questionDAO.getById(questionId);
  40. Set<Answer> answers = question.getAnswers();
  41. Set<Answer> userAnswers = userDAO.findAnswers(userId);
  42. if(!userAnswers.isEmpty()){
  43. userAnswers.retainAll(answers);
  44. return userAnswers.size() > 0;
  45. }
  46. return false;
  47. }
  48.  
  49. }

Per tal que Set.retailAll trobi les preguntes contingudes als sets answers i userAnswers s’ha d’especificar què vol dir aquesta igualtat. En el cas de Answers, dues preguntes seran igual si tenen el mateix valor que answerId.

  1. @Table(name = "answers")
  2. public class Answer implements Serializable {
  3. @Override
  4. public boolean equals(Object o) {
  5. if (this == o) return true;
  6. if (o == null || getClass() != o.getClass()) return false;
  7. Answer answer = (Answer) o;
  8.  
  9. return !(getAnswerId() != null ? !getAnswerId().equals(answer.getAnswerId()) : answer.getAnswerId() != null);
  10. }
  11.  
  12. @Override
  13. public int hashCode() {
  14. return getText() != null ? getText().hashCode() : 0;
  15. }
  16. }

Detecció dels usuaris que ja han contestat preguntes

L’objectiu d’aquesta activitat és escriure els tests necessaris per detectar si un usuari ja ha contestat una pregunta. Per fer-ho, afegiu tests a QuestionServiceTest i UserHibernateDAO i creeu el test org.ioc.daw.answer.AnswerTest que comprovi que la implementació de la igualtat és correcta.

  1. public class AnswerTest {
  2. @Test
  3. public void checkAnswersAreEqual() {
  4. Answer answer1 = new Answer();
  5. answer1.setAnswerId(1);
  6. answer1.setText("Answer1");
  7. Answer answer2 = new Answer();
  8. answer2.setAnswerId(1);
  9. answer2.setText("Answer1");
  10. Assert.assertTrue(answer2.equals(answer1));
  11. }
  12.  
  13. @Test
  14. public void checkAnswersAreDifferent() {
  15. Answer answer1 = new Answer();
  16. answer1.setAnswerId(1);
  17. answer1.setText("Answer1");
  18. Answer answer2 = new Answer();
  19. answer2.setAnswerId(2);
  20. answer2.setText("Answer2");
  21. Assert.assertFalse(answer2.equals(answer1));
  22. }
  23. }
  24.  
  25. @RunWith(SpringJUnit4ClassRunner.class)
  26. @ContextConfiguration(classes = {EmbeddedDatabaseTestConfig.class})
  27. public class UserDAOTest {
  28. @Test
  29. public void findAllUserAnswers() {
  30. User user1 =new User();
  31. user1.setUsername("test");
  32. user1.setActive(true);
  33. user1.setEmail(""email@test.com");
  34. user1.setPassword("password");
  35. user1.setName("name");
  36. user1.setCreatedOn(new Timestamp(new Date().getTime()));
  37.  
  38. Answer answer1 = new Answer();
  39. answer1.setText("Answer1");
  40. Answer answer2 = new Answer();
  41. answer2.setText("Answer2");
  42. Set<Answer> answers = new HashSet<>();
  43. answers.add(answer1);
  44. answers.add(answer2);
  45. user1.setAnswers(answers);
  46. userDAO.create(user1);
  47.  
  48. User userFromDB = userDAO.getById(user1.getUserId());
  49. assertEquals(2, userFromDB.getAnswers().size());
  50. }
  51. }

Abans d’executar els tests (@Before) utilitzarem el mètode Mockito.reset per evitar que hi hagi efectes residuals dels mocks en els diferents tests.

  1. @ContextConfiguration(classes = {SpringTestConfig.class})
  2. public class QuestionServiceTest {
  3. @Before
  4. public void setUp(){
  5. Mockito.reset(questionDAOMock);
  6. Mockito.reset(userDAOMock);
  7. }
  8.  
  9. @Test
  10. public void checkUserCanOnlyAnswerOnce() {
  11. int userID = 1;
  12. int questionId = 1;
  13. int answerId = 1;
  14. Question question1 = getDummyQuestion(questionId);
  15. Answer answer1 = getDummyAnswer(answerId);
  16. Set<Answer> answers = new HashSet<>();
  17. answers.add(answer1);
  18. question1.setAnswers(answers);
  19. when(questionDAOMock.getById(questionId)).thenReturn(question1);
  20.  
  21. User user1 = getDummyUser(userID);
  22. Answer userAnswer1 = getDummyAnswer(answerId);
  23. Answer userAnswer2 = getDummyAnswer(2);
  24. Set<Answer> userAnswers = new HashSet<>();
  25. userAnswers.add(userAnswer1);
  26. userAnswers.add(userAnswer2);
  27. user1.setAnswers(userAnswers);
  28. when(userDAOMock.getById(userID)).thenReturn(user1);
  29.  
  30. verify(questionDAOMock, never()).update(Mockito.any(Question.class));
  31. }
  32. }
  33.  
  34. @Import(value = {ServicesConfig.class})
  35. public class SpringTestConfig {
  36. @Bean
  37. public UserDAO userDAO() {
  38. return Mockito.mock(UserDAO.class);
  39. }
  40.  
  41. @Bean
  42. public QuestionDAO questionDAO() {
  43. return Mockito.mock(QuestionDAO.class);
  44. }
  45.  
  46. @Bean
  47. public AnswerDAO answerDAO() {
  48. return Mockito.mock(AnswerDAO.class);
  49. }
  50.  
  51. @Bean
  52. public PlatformTransactionManager transactionManager() {
  53. return Mockito.mock(PlatformTransactionManager.class);
  54. }
  55.  
  56. }

Anar a la pàgina anterior:
Accés a dades amb Spring i Hibernate
Anar a la pàgina següent:
Exercicis d'autoavaluació