Skip to content

Commit 34ee020

Browse files
committed
EGC-581 - increase test coverage
1 parent 6195308 commit 34ee020

2 files changed

Lines changed: 382 additions & 0 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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+
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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 StudentDeleteMergeEventHandlerServiceTest {
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 StudentDeleteMergeEventHandlerService service;
52+
53+
@Before
54+
public void setUp() {
55+
service = new StudentDeleteMergeEventHandlerService(
56+
eventRepository, restUtils, chesEmailService, applicationProperties, messagePublisher);
57+
}
58+
59+
@Test
60+
public void processStudentsMergeInfo_whenEitherStudentExists_shouldSendEmail() throws Exception {
61+
// Given
62+
val student = createMockStudent("student-1", "123456789");
63+
val trueStudent = createMockStudent("student-2", "123456788");
64+
65+
// Mock one student found, one not found (OR logic)
66+
val gradStudent1 = createMockGradStudent("student-1", false);
67+
val gradStudent2 = createMockGradStudent("student-2", true);
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_whenBothStudentsExist_shouldSendEmail() throws Exception {
88+
// Given
89+
val student = createMockStudent("student-1", "123456789");
90+
val trueStudent = createMockStudent("student-2", "123456788");
91+
92+
// Mock both students found (OR logic - both found = true)
93+
val gradStudent1 = createMockGradStudent("student-1", false);
94+
val gradStudent2 = createMockGradStudent("student-2", false);
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).sendEmail(any(), any(), any());
111+
}
112+
113+
@Test
114+
public void processStudentsMergeInfo_whenNeitherStudentExists_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 (OR logic - both not found = false)
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+
"123456789 DEMERGED FROM 123456788 IN PEN, NOT DEMERGED IN GRAD",
167+
"123456789 DEMERGED FROM 123456788 IN PEN, NOT DEMERGED IN GRAD");
168+
}
169+
170+
@Test
171+
public void getEventType_shouldReturnDeleteMerge() {
172+
// When
173+
val eventType = service.getEventType();
174+
175+
// Then
176+
assertThat(eventType).isEqualTo("DELETE_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

Comments
 (0)