Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TEST] FarmSchedule 테스트코드 작성 #137

Merged
merged 22 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ permissions:

jobs:
test:
env:
IMP_API_KEY: ${{ secrets.IMP_API_KEY }}
IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand All @@ -21,6 +26,9 @@ jobs:
with:
java-version: '21'
distribution: 'adopt'
env:
IMP_API_KEY: ${{ secrets.IMP_API_KEY }}
IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }}

- name: Cache Gradle packages
uses: actions/cache@v3
Expand All @@ -29,12 +37,22 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
env:
IMP_API_KEY: ${{ secrets.IMP_API_KEY }}
IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }}

- name: Upload test report
if: always()
uses: actions/upload-artifact@v3
with:
name: test-report
path: build/reports/tests/test

- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

- name: Run tests
run: ./gradlew test
run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
7 changes: 6 additions & 1 deletion src/main/java/poomasi/domain/farm/entity/Farm.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class Farm {
List<Review> reviewList = new ArrayList<>();

@Builder
public Farm(Long id, String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description, int experiencePrice, Integer maxCapacity, Integer maxReservation) {
public Farm(Long id, String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description, int experiencePrice, Integer maxCapacity, Integer maxReservation, LocalDateTime deletedAt) {
this.id = id;
this.name = name;
this.ownerId = ownerId;
Expand All @@ -92,6 +92,7 @@ public Farm(Long id, String name, Long ownerId, String address, String addressDe
this.experiencePrice = experiencePrice;
this.maxCapacity = maxCapacity;
this.maxReservation = maxReservation;
this.deletedAt = deletedAt;
}

public Farm updateFarm(FarmUpdateRequest farmUpdateRequest) {
Expand All @@ -115,4 +116,8 @@ public void updateMaxCapacity(Integer maxCapacity) {
public void updateMaxReservation(Integer maxReservation) {
this.maxReservation = maxReservation;
}

public void delete() {
this.deletedAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package poomasi.domain.farm._schedule.service;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import poomasi.domain.farm._schedule.dto.FarmScheduleRequest;
import poomasi.domain.farm._schedule.dto.FarmScheduleResponse;
import poomasi.domain.farm._schedule.dto.FarmScheduleUpdateRequest;
import poomasi.domain.farm._schedule.entity.FarmSchedule;
import poomasi.domain.farm._schedule.repository.FarmScheduleRepository;
import poomasi.global.error.BusinessException;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static poomasi.global.error.BusinessError.*;

@ExtendWith(MockitoExtension.class)
class FarmScheduleServiceTest {
@InjectMocks
private FarmScheduleService farmScheduleService;

@Mock
private FarmScheduleRepository farmScheduleRepository;

@Nested
@DisplayName("농장 스케줄 추가")
class AddFarmSchedule {
@Test
@DisplayName("정상적으로 스케줄을 추가한다")
void should_addFarmSchedule() {
// given
FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(10, 0), LocalTime.of(12, 0));

given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(List.of());

// when
farmScheduleService.addFarmSchedule(request);

// then
FarmSchedule farmSchedule = FarmSchedule.builder()
.farmId(1L)
.date(LocalDate.now())
.startTime(LocalTime.of(10, 0))
.endTime(LocalTime.of(12, 0))
.build();
assertAll(
() -> assertEquals(1L, farmSchedule.getFarmId()),
() -> assertEquals(LocalDate.now(), farmSchedule.getDate()),
() -> assertEquals(LocalTime.of(10, 0), farmSchedule.getStartTime()),
() -> assertEquals(LocalTime.of(12, 0), farmSchedule.getEndTime())
);
}

@Test
@DisplayName("시작 시간이 종료 시간보다 늦은 경우 예외를 발생시킨다")
void should_throwException_when_startTimeIsAfterEndTime() {
// given
FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(10, 0), LocalTime.of(9, 0));

// when & then
BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request));
assertEquals(START_TIME_SHOULD_BE_BEFORE_END_TIME, exception.getBusinessError());
}

@Test
@DisplayName("이미 등록된 스케줄이 있는 경우 예외를 발생시킨다")
void should_throwException_when_scheduleAlreadyExists() {
// given
FarmSchedule farmSchedule = FarmSchedule.builder()
.startTime(LocalTime.of(10, 0))
.endTime(LocalTime.of(12, 0))
.build();
List<FarmSchedule> farmSchedules = List.of(farmSchedule);

given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(farmSchedules);

FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(11, 0), LocalTime.of(13, 0));

// when & then
BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request));
assertEquals(FARM_SCHEDULE_ALREADY_EXISTS, exception.getBusinessError());
}

@Test
@DisplayName("중복된 스케줄이 있는 경우 save 메서드가 호출되지 않는다")
void should_notCallSave_when_scheduleAlreadyExists() {
// given
FarmSchedule farmSchedule = FarmSchedule.builder()
.startTime(LocalTime.of(10, 0))
.endTime(LocalTime.of(12, 0))
.build();
List<FarmSchedule> farmSchedules = List.of(farmSchedule);

given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(farmSchedules);

FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(11, 0), LocalTime.of(13, 0));

// when & then
assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request));
verify(farmScheduleRepository, never()).save(any(FarmSchedule.class));
}
}

@Nested
@DisplayName("농장 스케줄 조회")
class GetFarmSchedules {
@Test
@DisplayName("텅 빈 스케줄을 조회한다")
void should_getEmptyFarmSchedules() {
// given
LocalDate date = LocalDate.now();
given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of());

// when
List<FarmSchedule> farmSchedules = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date);

// then
assertTrue(farmSchedules.isEmpty());
}

@Test
@DisplayName("특정 날짜의 스케줄을 조회한다")
void should_getFarmSchedulesBySpecificDate() {
// given
LocalDate date = LocalDate.now();
FarmSchedule farmSchedule = FarmSchedule.builder()
.farmId(1L)
.date(date)
.startTime(LocalTime.of(10, 0))
.endTime(LocalTime.of(12, 0))
.build();
given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of(farmSchedule));

// when
List<FarmSchedule> farmSchedules = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date);

// then
assertAll(
() -> assertEquals(1, farmSchedules.size()),
() -> assertEquals(1L, farmSchedules.get(0).getFarmId()),
() -> assertEquals(date, farmSchedules.get(0).getDate()),
() -> assertEquals(LocalTime.of(10, 0), farmSchedules.get(0).getStartTime()),
() -> assertEquals(LocalTime.of(12, 0), farmSchedules.get(0).getEndTime())
);
}

@Test
@DisplayName("스케줄이 없는 날짜에 대해 빈 리스트를 반환한다")
void should_returnEmptyList_when_noSchedulesOnDate() {
// given
LocalDate date = LocalDate.of(2024, 11, 12);
given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of());

// when
List<FarmSchedule> result = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date);

// then
assertTrue(result.isEmpty());
}

@Test
@DisplayName("특정 월에 해당하는 스케줄을 올바르게 조회한다")
void should_returnSchedulesWithinSpecifiedMonth() {
// given
LocalDate startDate = LocalDate.of(2024, 11, 1);
LocalDate endDate = LocalDate.of(2024, 11, 30);
FarmSchedule farmSchedule = FarmSchedule.builder()
.farmId(1L)
.date(LocalDate.of(2024, 11, 10))
.startTime(LocalTime.of(10, 0))
.endTime(LocalTime.of(12, 0))
.build();

given(farmScheduleRepository.findByFarmIdAndDateRange(1L, startDate, endDate)).willReturn(List.of(farmSchedule));

// when
FarmScheduleRequest request = new FarmScheduleRequest(1L, 2024, 11);
List<FarmScheduleResponse> result = farmScheduleService.getFarmSchedulesByYearAndMonth(request);

// then
assertEquals(1, result.size());
assertEquals(farmSchedule.getDate(), result.get(0).date());
assertEquals(farmSchedule.getStartTime(), result.get(0).startTime());
assertEquals(farmSchedule.getEndTime(), result.get(0).endTime());
}

@Test
@DisplayName("존재하지 않는 스케줄 ID로 조회 시 예외가 발생한다")
void should_throwException_when_scheduleIdNotFound() {
// given
Long invalidId = 999L;
given(farmScheduleRepository.findById(invalidId)).willReturn(Optional.empty());

// when & then
BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.getFarmScheduleByScheduleId(invalidId));
assertEquals(FARM_SCHEDULE_NOT_FOUND, exception.getBusinessError());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,41 @@ void should_deleteFarm_when_ownerMatches() {
// then
verify(farmRepository).delete(farm);
}

@Test
@DisplayName("농장이 존재하지 않는 경우 예외를 발생시킨다")
void should_throwException_when_farmNotExistOnDelete() {
// given
Long farmId = 1L;
Long farmerId = 1L;
given(farmRepository.findByIdAndDeletedAtIsNull(farmId)).willReturn(Optional.empty());

// when & then
assertThatThrownBy(() -> farmFarmerService.deleteFarm(farmerId, farmId))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND);
}

@Test
@DisplayName("농장이 이미 삭제된 경우 예외를 발생시킨다")
void should_throwException_when_farmAlreadyDeleted() {
// given
Long farmId = 1L;
Long farmerId = 1L;
Farm farm = Farm.builder()
.id(farmId)
.name("Farm")
.ownerId(farmerId)
.deletedAt(null)
.build();

given(farmRepository.findByIdAndDeletedAtIsNull(farmId)).willReturn(Optional.of(farm));

// when
farmFarmerService.deleteFarm(farmerId, farmId);

// then
verify(farmRepository).delete(farm);
}
}
}
13 changes: 13 additions & 0 deletions src/test/java/poomasi/domain/farm/service/FarmServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ void should_throwException_when_farmNotExist() {
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND);
}

@Test
@DisplayName("농장이 삭제된 경우 예외를 발생시킨다")
void should_throwException_when_farmIsDeleted() {
// given
Farm farm = FarmTestHelper.makeRandomFarm();
farm.delete();

// when & then
assertThatThrownBy(() -> farmService.getFarmByFarmId(farm.getId()))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND);
}
}

}
Loading
Loading