Skip to content

Commit

Permalink
[feat][#47]알림 로직 수정 및 통합테스트 완료
Browse files Browse the repository at this point in the history
  • Loading branch information
sejoon00 committed Aug 14, 2024
1 parent 9fb119d commit 12dc659
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ jobs:
- name: build
run: |
chmod +x gradlew
./gradlew build -x test -x openapi3
./gradlew build -x openapi3
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import com.server.bbo_gak.domain.notification.dao.NotificationRepository;
import com.server.bbo_gak.domain.notification.entity.Notification;
import com.server.bbo_gak.domain.recruit.dao.RecruitRepository;
import com.server.bbo_gak.domain.recruit.dao.RecruitScheduleRepository;
import com.server.bbo_gak.domain.recruit.entity.Recruit;
import com.server.bbo_gak.domain.recruit.entity.RecruitSchedule;
import com.server.bbo_gak.domain.recruit.entity.RecruitStatusCategory;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.AbstractMap.SimpleEntry;
Expand All @@ -23,18 +22,22 @@
@RequiredArgsConstructor
public class NotificationScheduler {

private final RecruitRepository recruitRepository;
private final NotificationRepository notificationRepository;
private final RecruitScheduleRepository recruitScheduleRepository;

//TODO:스케줄러 추가시 application.yml의 ThreadPool 개수를 증가시켜줘야합니다.

@Scheduled(cron = "0 0 0 * * ?")
@Transactional
public void executeAtMidnight() {
log.info("유저별 마감 하루 남은 공고 알림 생성");
List<Recruit> allRecruits = recruitRepository.findAll();

List<Entry<Recruit, RecruitSchedule>> recruitsWithOneDayLeft = findRecruitsWithOneDayLeft(allRecruits);
LocalDate now = LocalDate.now();
List<RecruitSchedule> scheduleList = recruitScheduleRepository.findAllByDeadLineBetween(now,
now.plusDays(1));

List<Entry<Recruit, RecruitSchedule>> recruitsWithOneDayLeft = getRecruitAndScheduleMaps(scheduleList);

List<Notification> notifications = createNotifications(recruitsWithOneDayLeft);

notificationRepository.saveAll(notifications);
Expand All @@ -54,13 +57,9 @@ public void deleteOldNotificationsAtMidnight() {
notificationRepository.deleteAll(notificationsToDelete);
}

private List<Entry<Recruit, RecruitSchedule>> findRecruitsWithOneDayLeft(List<Recruit> allRecruits) {
return allRecruits.stream()
.filter(recruit -> !RecruitStatusCategory.isRejectionStatus(recruit.getRecruitStatus()))
.flatMap(recruit -> recruit.getScheduleList().stream()
.filter(this::isDeadlineWithinOneDay)
.map(schedule -> new SimpleEntry<>(recruit, schedule))
)
private List<Entry<Recruit, RecruitSchedule>> getRecruitAndScheduleMaps(List<RecruitSchedule> scheduleList) {
return scheduleList.stream()
.map(schedule -> new SimpleEntry<>(schedule.getRecruit(), schedule))
.collect(Collectors.toList());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
Expand All @@ -27,8 +28,10 @@ public List<NotificationGetResponse> getNotificationList(User user) {
.toList();
}

@Transactional
public void updateAllNotificationToRead(User user) {
notificationRepository.findAllByUserAndIsReadFalse(user)
.forEach(Notification::updateReadTrue);
List<Notification> notificationList = notificationRepository.findAllByUserAndIsReadFalse(user);
notificationList.forEach(Notification::updateReadTrue);
notificationRepository.saveAll(notificationList);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.server.bbo_gak.domain.recruit.dao;

import com.server.bbo_gak.domain.recruit.entity.RecruitSchedule;
import java.time.LocalDate;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RecruitScheduleRepository extends JpaRepository<RecruitSchedule, Long> {

List<RecruitSchedule> findAllByDeadLineBetween(LocalDate now, LocalDate nowPlusOneDay);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpMethod;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Rollback(true)
@SpringBootTest
@ActiveProfiles("test")
@Sql("/auth-test-data.sql")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,18 @@
import org.springframework.test.context.jdbc.Sql;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
@ActiveProfiles("test")
@Sql("/card-test-data.sql")
public class CardControllerTest extends AbstractRestDocsTests {

private static final String DEFAULT_URL = "/api/v1";
@Autowired
private CardRepository cardRepository;

@Autowired
private CardTagRepository cardTagRepository;

private static final String DEFAULT_URL = "/api/v1";

@Nested
class 카드_타입_카운트_조회 {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.server.bbo_gak.domain.notification.controller;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.server.bbo_gak.domain.notification.dao.NotificationRepository;
import com.server.bbo_gak.domain.notification.dto.response.NotificationGetNumResponse;
import com.server.bbo_gak.domain.notification.dto.response.NotificationGetResponse;
import com.server.bbo_gak.domain.notification.entity.Notification;
import com.server.bbo_gak.domain.notification.entity.NotificationType;
import com.server.bbo_gak.domain.notification.service.NotificationService;
import com.server.bbo_gak.domain.notification.service.NotificationScheduler;
import com.server.bbo_gak.global.AbstractRestDocsTests;
import com.server.bbo_gak.global.RestDocsFactory;
import java.lang.reflect.Field;
Expand All @@ -20,36 +20,48 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpMethod;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
@ActiveProfiles("test")
@Sql("/notification-test-data.sql")
public class NotificationControllerTest extends AbstractRestDocsTests {

private static final String DEFAULT_URL = "/api/v1/notifications";

@MockBean
private NotificationService notificationService;
@Autowired
private NotificationScheduler notificationScheduler;

@Autowired
private NotificationRepository notificationRepository;

@Autowired
private RestDocsFactory restDocsFactory;

@BeforeEach
void setUp() {
notificationScheduler.executeAtMidnight();
}

@Nested
class 알림개수_조회 {

@Test
public void 성공() throws Exception {
NotificationGetNumResponse response = new NotificationGetNumResponse(3L);
when(notificationService.getNotificationNum(any())).thenReturn(response);
NotificationGetNumResponse response = new NotificationGetNumResponse(1L);

mockMvc.perform(
restDocsFactory.createRequest(DEFAULT_URL + "/num", null, HttpMethod.GET, objectMapper))
.andExpect(status().isOk())
.andDo(
restDocsFactory.getSuccessResource("[GET] 알림 개수 조회 성공", "알림 개수 조회", "Notification", null,
response));

assertEquals(1, notificationRepository.findAll().size());
}
}

Expand Down Expand Up @@ -88,10 +100,6 @@ void setUp() {

@Test
public void 성공() throws Exception {

// NotificationGetResponse DTO 객체 생성
when(notificationService.getNotificationList(any())).thenReturn(List.of(response));

mockMvc.perform(
restDocsFactory.createRequest(DEFAULT_URL, null, HttpMethod.GET, objectMapper))
.andExpect(status().isOk())
Expand All @@ -106,14 +114,15 @@ class 알림읽음표시_업데이트 {

@Test
public void 성공() throws Exception {
doNothing().when(notificationService).updateAllNotificationToRead(any());

mockMvc.perform(
restDocsFactory.createRequest(DEFAULT_URL, null, HttpMethod.PUT, objectMapper))
.andExpect(status().isOk())
.andDo(
restDocsFactory.getSuccessResourceList("[PUT] 알림 읽음 표시 업데이트 성공", "알림 읽음 표시 업데이트", "Notification",
List.of(), List.of()));
Notification notification = notificationRepository.findById(1L).get();
System.out.println(notification.getTitle());
assertTrue(notification.isRead());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.server.bbo_gak.domain.notification.service;

import static org.junit.jupiter.api.Assertions.assertEquals;

import com.server.bbo_gak.domain.notification.dao.NotificationRepository;
import com.server.bbo_gak.domain.notification.entity.Notification;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;

@SpringBootTest
@ActiveProfiles("test")
@Sql("/notification-test-data.sql")
public class NotificationSchedulerTest {

@Autowired
private NotificationScheduler notificationScheduler;

@Autowired
private NotificationRepository notificationRepository;

@Test
public void 자정알림생성_성공() {

// when: 스케줄러 실행
notificationScheduler.executeAtMidnight();

// then: Notification이 잘 생성되었는지 검증
List<Notification> notifications = notificationRepository.findAll();
assertEquals(1, notifications.size());
}
}
37 changes: 37 additions & 0 deletions src/test/resources/notification-test-data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
delete
from notification;

delete
from recruit_schedule;

delete
from recruit;

delete
from recruit_season;

delete
from users;


INSERT INTO users (deleted, created_at, update_at, user_id, dtype, email, login_id, name, password, role)
VALUES (false, '2024-07-24 21:27:20.000000', '2024-07-24 21:27:21.000000', 1, '1', null, 'test', 'test', 'test',
'USER');

-- 다음으로 recruit_season 테이블에 데이터를 삽입합니다.
INSERT INTO recruit_season (recruit_season_id, name, user_id)
VALUES (1, '2024 상반기', 1);
INSERT INTO recruit_season (recruit_season_id, name, user_id)
VALUES (2, '2024 하반기', 1);

INSERT INTO recruit (recruit_id, title, site_url, recruit_status, recruit_season_id, user_id, created_at, update_at,
deleted)
VALUES (1, 'Title for one day left', 'http://example.com/1', 'DOCUMENT_PASSED', 1, 1, CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP, false),
(2, 'Title for more than one day left', 'http://example.com/2', 'PREPARATION_IN_PROGRESS', 2, 1,
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, false);

-- RecruitSchedule 테이블에 데이터 삽입
INSERT INTO recruit_schedule (recruit_schedule_id, recruit_id, recruit_schedule_stage, dead_line)
VALUES (1, 1, 'FIRST_INTERVIEW', CURRENT_DATE + 1), -- 하루 남은 스케줄
(2, 2, 'CLOSING_DOCUMENT', CURRENT_DATE + 2); -- 하루 이상 남은 스케줄

0 comments on commit 12dc659

Please sign in to comment.