1+ package ca .bc .gov .educ .api .trax .service ;
2+
3+ import ca .bc .gov .educ .api .trax .messaging .MessagePublisher ;
4+ import ca .bc .gov .educ .api .trax .properties .ApplicationProperties ;
5+ import ca .bc .gov .educ .api .trax .repository .EventRepository ;
6+ import ca .bc .gov .educ .api .trax .rest .RestUtils ;
7+ import ca .bc .gov .educ .api .trax .struct .CHESEmail ;
8+ import ca .bc .gov .educ .api .trax .struct .GradStudent ;
9+ import ca .bc .gov .educ .api .trax .struct .Student ;
10+ import ca .bc .gov .educ .api .trax .support .NatsMessageImpl ;
11+ import ca .bc .gov .educ .api .trax .util .JsonUtil ;
12+ import lombok .val ;
13+ import org .junit .Before ;
14+ import org .junit .Test ;
15+ import org .junit .runner .RunWith ;
16+ import org .mockito .ArgumentCaptor ;
17+ import org .mockito .Captor ;
18+ import org .mockito .Mock ;
19+ import org .mockito .junit .MockitoJUnitRunner ;
20+
21+ import java .util .concurrent .CompletableFuture ;
22+
23+ import static org .assertj .core .api .Assertions .assertThat ;
24+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
25+ import ca .bc .gov .educ .api .trax .exception .NotificationApiException ;
26+ import static org .mockito .ArgumentMatchers .any ;
27+ import static org .mockito .ArgumentMatchers .anyString ;
28+ import static org .mockito .Mockito .*;
29+
30+ @ RunWith (MockitoJUnitRunner .class )
31+ public class StudentCreateMergeEventHandlerServiceTest {
32+
33+ @ Mock
34+ private RestUtils restUtils ;
35+
36+ @ Mock
37+ private CHESEmailService chesEmailService ;
38+
39+ @ Mock
40+ private EventRepository eventRepository ;
41+
42+ @ Mock
43+ private ApplicationProperties applicationProperties ;
44+
45+ @ Mock
46+ private MessagePublisher messagePublisher ;
47+
48+ @ Captor
49+ private ArgumentCaptor <CHESEmail > emailCaptor ;
50+
51+ private StudentCreateMergeEventHandlerService service ;
52+
53+ @ Before
54+ public void setUp () {
55+ service = new StudentCreateMergeEventHandlerService (
56+ eventRepository , restUtils , chesEmailService , applicationProperties , messagePublisher );
57+ }
58+
59+ @ Test
60+ public void processStudentsMergeInfo_whenBothStudentsExist_shouldSendEmail () throws Exception {
61+ // Given
62+ val student = createMockStudent ("student-1" , "123456789" );
63+ val trueStudent = createMockStudent ("student-2" , "123456788" );
64+
65+ // Mock both students found in GRAD-STUDENT-API
66+ val gradStudent1 = createMockGradStudent ("student-1" , false );
67+ val gradStudent2 = createMockGradStudent ("student-2" , false );
68+
69+ val natsMsgImpl1 = new NatsMessageImpl ();
70+ natsMsgImpl1 .setData (JsonUtil .getJsonBytesFromObject (gradStudent1 ));
71+
72+ val natsMsgImpl2 = new NatsMessageImpl ();
73+ natsMsgImpl2 .setData (JsonUtil .getJsonBytesFromObject (gradStudent2 ));
74+
75+ when (messagePublisher .requestMessage (anyString (), any ()))
76+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl1 ))
77+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl2 ));
78+
79+ // When
80+ service .processStudentsMergeInfo (student , trueStudent );
81+
82+ // Then
83+ verify (chesEmailService ).sendEmail (any (), any (), any ());
84+ }
85+
86+ @ Test
87+ public void processStudentsMergeInfo_whenOneStudentNotFound_shouldNotSendEmail () throws Exception {
88+ // Given
89+ val student = createMockStudent ("student-1" , "123456789" );
90+ val trueStudent = createMockStudent ("student-2" , "123456788" );
91+
92+ // Mock one student found, one not found
93+ val gradStudent1 = createMockGradStudent ("student-1" , false );
94+ val gradStudent2 = createMockGradStudent ("student-2" , true );
95+
96+ val natsMsgImpl1 = new NatsMessageImpl ();
97+ natsMsgImpl1 .setData (JsonUtil .getJsonBytesFromObject (gradStudent1 ));
98+
99+ val natsMsgImpl2 = new NatsMessageImpl ();
100+ natsMsgImpl2 .setData (JsonUtil .getJsonBytesFromObject (gradStudent2 ));
101+
102+ when (messagePublisher .requestMessage (anyString (), any ()))
103+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl1 ))
104+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl2 ));
105+
106+ // When
107+ service .processStudentsMergeInfo (student , trueStudent );
108+
109+ // Then
110+ verify (chesEmailService , never ()).sendEmail (any (), any (), any ());
111+ }
112+
113+ @ Test
114+ public void processStudentsMergeInfo_whenBothStudentsNotFound_shouldNotSendEmail () throws Exception {
115+ // Given
116+ val student = createMockStudent ("student-1" , "123456789" );
117+ val trueStudent = createMockStudent ("student-2" , "123456788" );
118+
119+ // Mock both students not found
120+ val gradStudent1 = createMockGradStudent ("student-1" , true );
121+ val gradStudent2 = createMockGradStudent ("student-2" , true );
122+
123+ val natsMsgImpl1 = new NatsMessageImpl ();
124+ natsMsgImpl1 .setData (JsonUtil .getJsonBytesFromObject (gradStudent1 ));
125+
126+ val natsMsgImpl2 = new NatsMessageImpl ();
127+ natsMsgImpl2 .setData (JsonUtil .getJsonBytesFromObject (gradStudent2 ));
128+
129+ when (messagePublisher .requestMessage (anyString (), any ()))
130+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl1 ))
131+ .thenReturn (CompletableFuture .completedFuture (natsMsgImpl2 ));
132+
133+ // When
134+ service .processStudentsMergeInfo (student , trueStudent );
135+
136+ // Then
137+ verify (chesEmailService , never ()).sendEmail (any (), any (), any ());
138+ }
139+
140+ @ Test
141+ public void processStudentsMergeInfo_whenApiError_shouldThrowRuntimeException () {
142+ // Given
143+ val student = createMockStudent ("student-1" , "123456789" );
144+ val trueStudent = createMockStudent ("student-2" , "123456788" );
145+
146+ when (messagePublisher .requestMessage (anyString (), any ()))
147+ .thenReturn (CompletableFuture .failedFuture (new RuntimeException ("API Error" )));
148+
149+ // When & Then
150+ assertThatThrownBy (() -> service .processStudentsMergeInfo (student , trueStudent ))
151+ .isInstanceOf (NotificationApiException .class )
152+ .hasMessageContaining ("Failed to check students" );
153+ }
154+
155+ @ Test
156+ public void prepareAndSendEmail_shouldCreateCorrectSubject () {
157+ // Given
158+ val pen = "123456789" ;
159+ val mergedToPen = "123456788" ;
160+
161+ // When
162+ service .prepareAndSendEmail (pen , mergedToPen );
163+
164+ // Then
165+ verify (chesEmailService ).sendEmail (null ,
166+ "MERGE DIFFERENCE: 123456789 MERGED TO 123456788 IN PEN, NOT MERGED IN GRAD" ,
167+ "MERGE DIFFERENCE: 123456789 MERGED TO 123456788 IN PEN, NOT MERGED IN GRAD" );
168+ }
169+
170+ @ Test
171+ public void getEventType_shouldReturnCreateMerge () {
172+ // When
173+ val eventType = service .getEventType ();
174+
175+ // Then
176+ assertThat (eventType ).isEqualTo ("CREATE_MERGE" );
177+ }
178+
179+ private Student createMockStudent (String studentId , String pen ) {
180+ val student = new Student ();
181+ student .setStudentID (studentId );
182+ student .setPen (pen );
183+ return student ;
184+ }
185+
186+ private GradStudent createMockGradStudent (String studentId , boolean notFound ) {
187+ return notFound ?
188+ GradStudent .builder ().studentID (studentId ).exception ("not found" ).build () :
189+ GradStudent .builder ().studentID (studentId ).program ("2018-EN" ).graduated ("Y" ).exception (null ).build ();
190+ }
191+ }
0 commit comments