Skip to content

Commit

Permalink
test: 지출 관리 단위 테스트 구현 (#59)
Browse files Browse the repository at this point in the history
* test: 지출이력 엔티티 단위 테스트 구현

* test: 지출 관리 서비스 로직 단위 테스트 구현
  • Loading branch information
gengminy committed Dec 14, 2023
1 parent a6d45f5 commit 7494762
Show file tree
Hide file tree
Showing 8 changed files with 383 additions and 7 deletions.
19 changes: 12 additions & 7 deletions src/main/java/com/testcar/car/domains/expense/ExpenseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@
public class ExpenseService {
private final CarStockService carStockService;
private final ExpenseRepository expenseRepository;

/** 조건에 맞는 지출 이력을 모두 조회합니다. */
public Page<ExpenseDto> findAllByCondition(
ExpenseFilterCondition condition, Pageable pageable) {
return expenseRepository.findAllPageByCondition(condition, pageable);
}

/** 지출 이력을 id로 조회합니다. */
public ExpenseDto findById(Long id) {
public ExpenseDto findById(Long expenseId) {
return expenseRepository
.findDetailById(id)
.findDetailById(expenseId)
.orElseThrow(() -> new NotFoundException(ErrorCode.EXPENSE_NOT_FOUND));
}

Expand All @@ -54,10 +55,14 @@ public Expense register(Member member, RegisterExpenseRequest request) {
}

/** 지출 이력을 수정합니다. */
public Expense update(Member member, Long id, RegisterExpenseRequest request) {
final ExpenseDto expenseDto = this.findById(id);
public Expense update(Member member, Long expenseId, RegisterExpenseRequest request) {
final ExpenseDto expenseDto = this.findById(expenseId);
final Expense expense = expenseDto.getExpense();
if (!Objects.equals(expenseDto.getStockNumber(), request.getStockNumber())) {
final String updateStockNumber = request.getStockNumber();

if (updateStockNumber == null) {
expense.updateCarStock(null);
} else if (!Objects.equals(expenseDto.getStockNumber(), request.getStockNumber())) {
final CarStock carStock = carStockService.findByStockNumber(request.getStockNumber());
expense.updateCarStock(carStock);
}
Expand All @@ -67,8 +72,8 @@ public Expense update(Member member, Long id, RegisterExpenseRequest request) {
}

/** 지출 이력을 삭제합니다. */
public Expense delete(Member member, Long gasStationHistoryId) {
final ExpenseDto expenseDto = this.findById(gasStationHistoryId);
public Expense delete(Member member, Long expenseId) {
final ExpenseDto expenseDto = this.findById(expenseId);
final Expense expense = expenseDto.getExpense();
expense.updateMemberBy(member);
expense.delete();
Expand Down
6 changes: 6 additions & 0 deletions src/test/java/com/testcar/car/common/Constant.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,10 @@ private Constant() {}
public static final String ANOTHER_GAS_STATION_NAME = "아무주유소B";
public static final double GAS_STATION_HISTORY_AMOUNT = 100.22;
public static final double ANOTHER_GAS_STATION_HISTORY_AMOUNT = 9999.22;

/** Expense */
public static final String EXPENSE_DESCRIPTION = "유류비";

public static final long EXPENSE_AMOUNT = 100000L;
public static final LocalDate EXPENSE_DATE = NOW.toLocalDate();
}
16 changes: 16 additions & 0 deletions src/test/java/com/testcar/car/common/DtoFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.testcar.car.domains.carStock.entity.CarStock;
import com.testcar.car.domains.carTest.model.vo.CarTestDto;
import com.testcar.car.domains.department.entity.Department;
import com.testcar.car.domains.expense.entity.Expense;
import com.testcar.car.domains.expense.model.dto.ExpenseDto;
import com.testcar.car.domains.gasStationHistory.entity.GasStationHistory;
import com.testcar.car.domains.gasStationHistory.model.dto.GasStationHistoryDto;
import com.testcar.car.domains.member.Member;
Expand Down Expand Up @@ -45,4 +47,18 @@ public static GasStationHistoryDto createGasStationHistoryDto() {
carStock.getStockNumber(),
department.getName());
}

public static ExpenseDto createExpenseDto(Expense expense) {
final Member member = MemberEntityFactory.createMember();
final Department department = member.getDepartment();
final CarStock carStock = createCarStock();
final Car car = carStock.getCar();
return new ExpenseDto(
expense,
member.getName(),
member.getName(),
car.getName(),
carStock.getStockNumber(),
department.getName());
}
}
21 changes: 21 additions & 0 deletions src/test/java/com/testcar/car/common/ExpenseEntityFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.testcar.car.common;

import static com.testcar.car.common.Constant.EXPENSE_AMOUNT;
import static com.testcar.car.common.Constant.EXPENSE_DATE;
import static com.testcar.car.common.Constant.EXPENSE_DESCRIPTION;

import com.testcar.car.domains.expense.entity.Expense;

public class ExpenseEntityFactory {
private ExpenseEntityFactory() {}

public static Expense createExpense() {
return Expense.builder()
.member(MemberEntityFactory.createMember())
.carStock(CarEntityFactory.createCarStock())
.description(EXPENSE_DESCRIPTION)
.amount(EXPENSE_AMOUNT)
.usedAt(EXPENSE_DATE)
.build();
}
}
199 changes: 199 additions & 0 deletions src/test/java/com/testcar/car/domains/expense/ExpenseServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package com.testcar.car.domains.expense;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.testcar.car.common.CarEntityFactory;
import com.testcar.car.common.DtoFactory;
import com.testcar.car.common.ExpenseEntityFactory;
import com.testcar.car.common.MemberEntityFactory;
import com.testcar.car.common.exception.NotFoundException;
import com.testcar.car.domains.carStock.CarStockService;
import com.testcar.car.domains.carStock.entity.CarStock;
import com.testcar.car.domains.expense.entity.Expense;
import com.testcar.car.domains.expense.model.RegisterExpenseRequest;
import com.testcar.car.domains.expense.model.dto.ExpenseDto;
import com.testcar.car.domains.expense.model.vo.ExpenseFilterCondition;
import com.testcar.car.domains.expense.repository.ExpenseRepository;
import com.testcar.car.domains.expense.request.ExpenseRequestFactory;
import com.testcar.car.domains.member.Member;
import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
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 org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

@ExtendWith(MockitoExtension.class)
public class ExpenseServiceTest {
@Mock private ExpenseRepository expenseRepository;
@Mock private CarStockService carStockService;
@InjectMocks private ExpenseService expenseService;

private static Member member;
private static CarStock carStock;
private static Expense expense;
private static ExpenseDto expenseDto;
private static final Long expenseId = 1L;

@BeforeAll
public static void setUp() {
member = MemberEntityFactory.createMember();
carStock = CarEntityFactory.createCarStock();
expense = ExpenseEntityFactory.createExpense();
expenseDto = DtoFactory.createExpenseDto(expense);
}

@Test
void 조건에_맞는_모든_지출내역을_DB에서_조회한다() {
// given
final ExpenseFilterCondition condition = new ExpenseFilterCondition();
Pageable pageable = mock(Pageable.class);
Page<ExpenseDto> mockPage = mock(Page.class);
when(expenseRepository.findAllPageByCondition(condition, pageable)).thenReturn(mockPage);

// when
final Page<ExpenseDto> result = expenseService.findAllByCondition(condition, pageable);

// then
assertEquals(mockPage, result);
verify(expenseRepository).findAllPageByCondition(condition, pageable);
}

@Test
void 지출이력을_ID_조회한다() {
// given
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.of(expenseDto));
// when
final ExpenseDto result = expenseService.findById(expenseId);

// then
assertEquals(expenseDto, result);
verify(expenseRepository).findDetailById(expenseId);
}

@Test
void DB_해당_ID_지출이력이_없다면_오류가_발생한다() {
// given
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.empty());
// when, then
Assertions.assertThrows(
NotFoundException.class,
() -> {
expenseService.findById(expenseId);
});
}

@Test
void 재고번호_없이_지출이력을_등록한다() {
// given
final RegisterExpenseRequest request =
ExpenseRequestFactory.createRegisterExpenseRequestWithoutStock();
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);

// when
final Expense result = expenseService.register(member, request);

// then
assertEquals(expense, result);
verify(expenseRepository).save(any(Expense.class));
then(carStockService).shouldHaveNoInteractions();
}

@Test
void 재고번호를_포함하여_지출이력을_등록한다() {
// given
final RegisterExpenseRequest request =
ExpenseRequestFactory.createRegisterExpenseRequestWithStock();
when(carStockService.findByStockNumber(request.getStockNumber())).thenReturn(carStock);
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);

// when
final Expense result = expenseService.register(member, request);

// then
assertEquals(expense, result);
verify(expenseRepository).save(any(Expense.class));
verify(carStockService).findByStockNumber(request.getStockNumber());
}

@Test
void 재고번호가_없어지면_지출이력의_차량재고_정보를_제거한다() {
// given
final RegisterExpenseRequest request =
ExpenseRequestFactory.createRegisterExpenseRequestWithoutStock();
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.of(expenseDto));
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);

// when
final Expense result = expenseService.update(member, expenseId, request);

// then
assertEquals(expense, result);
verify(expenseRepository).findDetailById(expenseId);
verify(expenseRepository).save(any(Expense.class));
then(carStockService).shouldHaveNoInteractions();
}

@Test
void 재고번호가_변경되면_지출이력의_차량재고_정보를_수정한다() {
// given
final RegisterExpenseRequest request =
ExpenseRequestFactory.createRegisterExpenseRequestWithAnotherStock();
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.of(expenseDto));
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);
when(carStockService.findByStockNumber(request.getStockNumber())).thenReturn(carStock);

// when
final Expense result = expenseService.update(member, expenseId, request);

// then
assertEquals(expense, result);
verify(expenseRepository).findDetailById(expenseId);
verify(expenseRepository).save(any(Expense.class));
verify(carStockService).findByStockNumber(request.getStockNumber());
}

@Test
void 재고번호가_동일하면_지출이력_나머지_정보만_수정한다() {
// given
final RegisterExpenseRequest request =
ExpenseRequestFactory.createRegisterExpenseRequestWithStock();
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.of(expenseDto));
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);

// when
final Expense result = expenseService.update(member, expenseId, request);

// then
assertEquals(expense, result);
verify(expenseRepository).save(any(Expense.class));
verify(expenseRepository).findDetailById(expenseId);
then(carStockService).shouldHaveNoInteractions();
}

@Test
void 지출이력을_삭제한다() {
// given
when(expenseRepository.findDetailById(expenseId)).thenReturn(Optional.of(expenseDto));
when(expenseRepository.save(any(Expense.class))).thenReturn(expense);

// when
final Expense result = expenseService.delete(member, expenseId);

// then
assertEquals(expense, result);
assertTrue(result.getDeleted());
verify(expenseRepository).findDetailById(expenseId);
verify(expenseRepository).save(any(Expense.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.testcar.car.domains.expense.entity;

import static com.testcar.car.common.Constant.EXPENSE_AMOUNT;
import static com.testcar.car.common.Constant.EXPENSE_DATE;
import static com.testcar.car.common.Constant.EXPENSE_DESCRIPTION;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.testcar.car.common.CarEntityFactory;
import com.testcar.car.common.ExpenseEntityFactory;
import com.testcar.car.common.MemberEntityFactory;
import com.testcar.car.domains.carStock.entity.CarStock;
import com.testcar.car.domains.member.Member;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;

public class ExpenseTest {
@Test
public void 새로운_지출이력을_생성한다() {
// given
final Member member = MemberEntityFactory.createMember();
final CarStock carStock = CarStock.builder().build();
final String description = EXPENSE_DESCRIPTION;
final long amount = EXPENSE_AMOUNT;
final LocalDate usedAt = EXPENSE_DATE;

// when
final Expense expense =
Expense.builder()
.member(member)
.carStock(carStock)
.description(description)
.amount(amount)
.usedAt(usedAt)
.build();

// then
assertNotNull(expense);
assertEquals(expense.getMember(), member);
assertEquals(expense.getCarStock(), carStock);
assertEquals(expense.getDescription(), description);
assertEquals(expense.getAmount(), amount);
assertEquals(expense.getUsedAt(), usedAt);
}

@Test
void 지출이력의_차량재고_정보를_수정한다() {
// given
final Expense expense = ExpenseEntityFactory.createExpense();
final CarStock updateCarStock = CarEntityFactory.createCarStock();

// when
expense.updateCarStock(updateCarStock);

// then
assertEquals(expense.getCarStock(), updateCarStock);
}

@Test
void 지출이력의_수정인_정보를_수정한다() {
// given
final Expense expense = ExpenseEntityFactory.createExpense();
final Member updateMember = MemberEntityFactory.createMember();

// when
expense.updateMemberBy(updateMember);

// then
assertEquals(expense.getUpdateMember(), updateMember);
}

@Test
void 지출이력의_상세정보를_수정한다() {
// given
final Expense expense = ExpenseEntityFactory.createExpense();
final String updateDescription = EXPENSE_DESCRIPTION + "update";
final long updateAmount = EXPENSE_AMOUNT + 1000;
final LocalDate updateUsedAt = EXPENSE_DATE.plusDays(1);

// when
expense.update(updateDescription, updateAmount, updateUsedAt);

// then
assertEquals(expense.getDescription(), updateDescription);
assertEquals(expense.getAmount(), updateAmount);
assertEquals(expense.getUsedAt(), updateUsedAt);
}
}
Loading

0 comments on commit 7494762

Please sign in to comment.