1+ package com .outfitlab .project .domain .useCases .combinationAttempt ;
2+
3+ import com .outfitlab .project .domain .exceptions .UserNotFoundException ;
4+ import com .outfitlab .project .domain .interfaces .repositories .CombinationAttemptRepository ;
5+ import com .outfitlab .project .domain .interfaces .repositories .UserRepository ;
6+ import com .outfitlab .project .domain .model .CombinationAttemptModel ;
7+ import com .outfitlab .project .domain .model .CombinationModel ;
8+ import com .outfitlab .project .domain .model .UserModel ;
9+ import org .junit .jupiter .api .BeforeEach ;
10+ import org .junit .jupiter .api .Test ;
11+ import org .mockito .ArgumentCaptor ;
12+ import static org .junit .jupiter .api .Assertions .*;
13+ import static org .mockito .Mockito .*;
14+
15+ public class RegisterCombinationAttemptTest {
16+
17+ private CombinationAttemptRepository attemptRepository = mock (CombinationAttemptRepository .class );
18+ private UserRepository userRepository = mock (UserRepository .class );
19+
20+ private RegisterCombinationAttempt registerCombinationAttempt ;
21+
22+ private static final String VALID_EMAIL = "test@user.com" ;
23+ private static final String IMAGE_URL = "http://storage/img/attempt-123.jpg" ;
24+ private static final Long EXPECTED_SAVED_ID = 42L ;
25+ private static final Long VALID_COMBINATION_ID = 10L ;
26+
27+ private CombinationModel mockCombination ;
28+ private UserModel mockUser ;
29+
30+ @ BeforeEach
31+ void setUp () throws UserNotFoundException {
32+ mockCombination = mock (CombinationModel .class );
33+ mockUser = mock (UserModel .class );
34+ when (mockCombination .getId ()).thenReturn (VALID_COMBINATION_ID );
35+ registerCombinationAttempt = new RegisterCombinationAttempt (attemptRepository , userRepository );
36+ }
37+
38+
39+ @ Test
40+ public void shouldRegisterAttemptAndReturnSavedIdWhenAllDataIsValid () throws UserNotFoundException {
41+ givenRepositorySavesAttemptAndReturns (EXPECTED_SAVED_ID );
42+ givenUserExists (VALID_EMAIL , mockUser );
43+
44+ Long resultId = whenExecuteRegisterAttempt (VALID_EMAIL , mockCombination , IMAGE_URL );
45+
46+ thenResultMatchesExpectedId (resultId , EXPECTED_SAVED_ID );
47+ thenRepositoryWasCalledWithCorrectAttempt (mockUser , mockCombination , IMAGE_URL );
48+ thenUserConsultationWasCalled (VALID_EMAIL , 1 );
49+ }
50+
51+ @ Test
52+ public void shouldThrowIllegalArgumentExceptionWhenUserEmailIsNull () {
53+ String nullEmail = null ;
54+
55+ assertThrows (IllegalArgumentException .class ,
56+ () -> whenExecuteRegisterAttempt (nullEmail , mockCombination , IMAGE_URL ),
57+ "Debe lanzar IllegalArgumentException si el email es null." );
58+
59+ thenUserConsultationWasCalled (nullEmail , 0 );
60+ thenRepositorySaveWasNeverCalled ();
61+ }
62+
63+ @ Test
64+ public void shouldThrowIllegalArgumentExceptionWhenCombinationIsNull () throws UserNotFoundException {
65+ givenUserExists (VALID_EMAIL , mockUser );
66+
67+ assertThrows (IllegalArgumentException .class ,
68+ () -> whenExecuteRegisterAttempt (VALID_EMAIL , null , IMAGE_URL ),
69+ "Debe lanzar IllegalArgumentException si la combinación es null." );
70+
71+ thenUserConsultationWasCalled (VALID_EMAIL , 1 );
72+ thenRepositorySaveWasNeverCalled ();
73+ }
74+
75+ @ Test
76+ public void shouldThrowIllegalArgumentExceptionWhenCombinationIdIsNull () throws UserNotFoundException {
77+ CombinationModel invalidCombination = mock (CombinationModel .class );
78+ when (invalidCombination .getId ()).thenReturn (null );
79+ givenUserExists (VALID_EMAIL , mockUser );
80+
81+ assertThrows (IllegalArgumentException .class ,
82+ () -> whenExecuteRegisterAttempt (VALID_EMAIL , invalidCombination , IMAGE_URL ),
83+ "Debe lanzar IllegalArgumentException si el ID de la combinación es null." );
84+
85+ thenRepositorySaveWasNeverCalled ();
86+ }
87+
88+ @ Test
89+ public void shouldPropagateUserNotFoundExceptionWhenUserDoesNotExist () {
90+ givenUserDoesNotExist (VALID_EMAIL );
91+
92+ assertThrows (UserNotFoundException .class ,
93+ () -> whenExecuteRegisterAttempt (VALID_EMAIL , mockCombination , IMAGE_URL ),
94+ "Debe propagar UserNotFoundException si el usuario no existe." );
95+
96+ thenUserConsultationWasCalled (VALID_EMAIL , 1 );
97+ thenRepositorySaveWasNeverCalled ();
98+ }
99+
100+ @ Test
101+ public void shouldRegisterAttemptSuccessfullyWhenImageUrlIsNull () throws UserNotFoundException {
102+ givenRepositorySavesAttemptAndReturns (EXPECTED_SAVED_ID );
103+ givenUserExists (VALID_EMAIL , mockUser );
104+ String nullImageUrl = null ;
105+
106+ Long resultId = whenExecuteRegisterAttempt (VALID_EMAIL , mockCombination , nullImageUrl );
107+
108+ thenResultMatchesExpectedId (resultId , EXPECTED_SAVED_ID );
109+ thenRepositoryWasCalledWithCorrectAttempt (mockUser , mockCombination , nullImageUrl );
110+ }
111+
112+ @ Test
113+ public void shouldPropagateRuntimeExceptionWhenRepositoryFailsToSave () throws UserNotFoundException {
114+ givenRepositoryThrowsRuntimeException ();
115+ givenUserExists (VALID_EMAIL , mockUser );
116+
117+ assertThrows (RuntimeException .class ,
118+ () -> whenExecuteRegisterAttempt (VALID_EMAIL , mockCombination , IMAGE_URL ),
119+ "Debe propagar RuntimeException si el repositorio falla." );
120+
121+ thenRepositorySaveWasCalled (1 );
122+ }
123+
124+
125+ //privadosss
126+ private void givenUserExists (String email , UserModel user ) throws UserNotFoundException {
127+ when (userRepository .findUserByEmail (email )).thenReturn (user );
128+ }
129+
130+ private void givenUserDoesNotExist (String email ) {
131+ when (userRepository .findUserByEmail (email )).thenThrow (UserNotFoundException .class );
132+ }
133+
134+ private void givenRepositorySavesAttemptAndReturns (Long id ) {
135+ when (attemptRepository .save (any (CombinationAttemptModel .class ))).thenReturn (id );
136+ }
137+
138+ private void givenRepositoryThrowsRuntimeException () {
139+ doThrow (new RuntimeException ("DB Connection Error" )).when (attemptRepository ).save (any (CombinationAttemptModel .class ));
140+ }
141+
142+ private Long whenExecuteRegisterAttempt (String userEmail , CombinationModel combination , String imageUrl ) {
143+ return registerCombinationAttempt .execute (userEmail , combination , imageUrl );
144+ }
145+
146+ private void thenResultMatchesExpectedId (Long actualId , Long expectedId ) {
147+ assertNotNull (actualId , "El ID devuelto no debe ser nulo." );
148+ assertEquals (expectedId , actualId , "El ID debe coincidir con el ID simulado." );
149+ }
150+
151+ private void thenUserConsultationWasCalled (String email , int times ) {
152+ verify (userRepository , times (times )).findUserByEmail (email );
153+ }
154+
155+ private void thenRepositorySaveWasCalled (int times ) {
156+ verify (attemptRepository , times (times )).save (any (CombinationAttemptModel .class ));
157+ }
158+
159+ private void thenRepositorySaveWasNeverCalled () {
160+ verify (attemptRepository , never ()).save (any (CombinationAttemptModel .class ));
161+ }
162+
163+ private void thenRepositoryWasCalledWithCorrectAttempt (UserModel expectedUser , CombinationModel expectedCombination , String expectedUrl ) {
164+ ArgumentCaptor <CombinationAttemptModel > captor = ArgumentCaptor .forClass (CombinationAttemptModel .class );
165+ verify (attemptRepository , times (1 )).save (captor .capture ());
166+
167+ CombinationAttemptModel capturedAttempt = captor .getValue ();
168+
169+ assertEquals (expectedUser , capturedAttempt .getUser (), "El modelo debe contener el usuario correcto." );
170+ assertEquals (expectedCombination , capturedAttempt .getCombination (), "El modelo debe contener la combinación correcta." );
171+ assertEquals (expectedUrl , capturedAttempt .getImageUrl (), "La URL de la imagen debe coincidir." );
172+ }
173+ }
0 commit comments