개발일기

감면 혜택 및 취등록세 계산 관련 테스트 코드 작성기 본문

TDD

감면 혜택 및 취등록세 계산 관련 테스트 코드 작성기

한둥둥 2025. 4. 18. 10:52

사실 지금 회사 프로젝트 구조는 테스트 코드를 짜기에는 적합한 구조는 아니다. 하지만 그럼에도 불구하고 테스트 코드를 작성하였다. 

내가 테스트 코드를 작성한 몇가지 이유는 아래와 같다.

1. 부동산 관련 세금 정산은 오차가 있으면 안된다. 반드시, 검증을 통해 값이 올바르게 사용자에게 보여주는 지 확인이 가능해야 한다.

2. 특정 코드를 수정하면 다른 코드까지 사이드 이펙트가 번질 확률이 있다. 

3. 해당 코드는 한번 작성하면 부동산 정책이 바뀌지 않는 한 코드를 다시 작성할 이유가 없으며 추후에도 검증 코드를 리팩토링하여 재사용할 수 있다.

4. 우리가 원하는 MSA구조로 리팩토링 할 경우, 기존에 가지고 있는 테스트 코드를 리팩토링하여 활용할 확률이 있다. 

 

위에와 같은 이점 때문에 나는 테스트 코드를 작성하기 시작했다. 

 

 

부동산 조건 별 테스트 케이스이다. 사실 여기다가 주택외 부동산에대한 조건도 작성해야하지만, 단위테스트에서 충분히 검증해준다고 판단하고 제외해주었다. 

조건 금액 취득세 농특세 인지세 등기신청수수료 채권본인부담금 법정수수료 지방교육세 취득세 세율 지방교육세 세율 농특세 세율
조정지역 1주택 3억이상 6억이하 (85제곱 이하) 500,000,000원 5,000,000원 0원 150,000원 13,000원 746,744원 690,000원 500,000원 0.01 0.001 0
비조정지역 1주택 3억이상 6억이하(85제곱 이하) 500,000,000원 5,000,000원 0원 150,000원 13,000원 746,744원 690,000원 500,000원 0.01 0.001 0
조정지역_1주택 3억이상 6억이하(85제곱 이상) 500,000,000원 5,000,000원 1,00,000원 150,000원 13,000원 746,744원 690,000원 500,000원 0.01 0.001 0.002
비조정지역_1주택 3억이상 6억이하(85제곱 이상) 500,000,000원 5,000,000원 1,00,000원 150,000원 13,000원 746,744원 690,000원 500,000원 0.01 0.001 0.002
조정지역_1주택 6억초과 9억이하(85제곱 이하) 900,000,000원 27,000,000원 0원 150,000원 13,000원 1,602,628원 970,000원 2,700,000원 0.03 0.003 0
비조정지역_1주택 6억초과 9억이하(85제곱 이하) 900,000,000원 27,000,000원 0원 150,000원 13,000원 1,602,628원 970,000원 2,700,000원 0.03 0.003 0
조정지역_1주택 10억초과 20억이하 (85제곱 이하) 2,000,000,000원 60,000,000원 0원 350,000원 13,000원 3,561,395원 1,540,000원 6,000,000원 0.3 0.003 0
조정지역 2주택 6억이하 감면세혜택없음 (85제곱 이상) 500,000,000원 40,000,000원 3,000,000원 150,000원 13,000원 746,744원 690,000원 2,000,000원 0.8 0.004 0.006
비조정지역 2주택 6억이하 (85제곱 이하) 500,000,000원 5,000,000원 1,000,000원 150,000원 13,000원 746,744원 690,000원 500,000원 0.01 0.001 0.002
비조정지역_2주택 6억초과 9억이하(85제곱 이하) 900,000,000원 27,000,000원 0원 150,000원 13,000원 1,602,628원 970,000원 2,700,000원 0.03 0.003 0
2주택 조정대상 지역 9억초과 (85제곱 이하) 2,000,000,000원 160,000,000원 0원 350,000원 13,000원 3,561,395원 1,540,000원 8,000,000원 0.08 0.004 0
비조정지역 2주택 9억초과 (85제곱 이하) 2,000,000,000원 60,000,000원 0원 350,000원 13,000원 3,561,395원 1,540,000원 6,000,000원 0.3 0.003 0
조정대상 지역 3주택 (85제곱 이상) 2,000,000,000원 240,000,000원 20,000,000원 350,000원 13,000원 3,561,395원 1,540,000원 8,000,000원 0.12 0.004 0
비조정대상 지역 3주택 (85제곱 이상) 2,000,000,000원 160,000,000원 12,000,000원 350,000원 13,000원 3,561,395원 1,540,000원 6,000,000원 0.08 0.004 0.006
4주택 조정대상 지역 (85제곱 이상) 2,000,000,000원 240,000,000원 20,000,000원 350,000원 13,000원 3,561,395원 1,540,000원 8,000,000원 0.12 0.004 0.1
4주택 비조정대상 지역 (85제곱 이상) 2,000,000,000원 240,000,000원 12,000,000원 350,000원 13,000원 3,561,395원 1,540,000원 8,000,000원 0.12 0.004 0.06
1주택 생애최초주택 (85제곱이상) 500,000,000원 3,000,000원 1,000,000원 150,000원 13,000원 746,744원 690,000원 300,000원 0.01 0.001 0.02
1주택 생애최초소형주택(85제곱이하) 500,000,000원 2,000,000원 0원 150,000원 13,000원 746,744원 690,000원 200,000원 0.01 0.001 0
1주택 출산가구주택(85제곱이상) 500,000,000원 0원 1,000,000원 150,000원 13,000원 746,744원 690,000원 0원 0.01 0.001 0.002
수도권 주택 외 매매 천만원이상 1억 3천만원 미만 (85제곱이상) 100,000,000원 4,000,000원 400,000원 70,000원 13,000원 57,442원 350,000원 400,000원 0.04 0.004 0.002
수도권 주택 외 매매 1억3천만원 이상 2억 5천만원 미만(85제곱 이상) 200,000,000원 8,000,000원 800,000원 150,000원 13,000원 183,814원 440,000원 800,000원 0.04 0.002 0.002
수도권 주택 외 매매 2억 5천만원 이상(85제곱 이상) 400,000,000원 16,000,000원 1,600,000원 150,000원 13,000원 459,535원 610,000원 1,600,000원 0.04 0.002 0.002
비수도권 주택 외 매매 천만원이상 1억 3천만원 미만 (85제곱이상) 100,000,000원 4,000,000원 400,000원 70,000원 13,000원 57,442원 350,000원 400,000원 0.04 0.004 0.002
비수도권 주택 외 매매 1억3천만원 이상 2억 5천만원 미만(85제곱 이상) 200,000,000원 8,000,000원 800,000원 150,000원 13,000원 183,814원 440,000원 800,000원 0.04 0.002 0.002
비수도권 주택 외 매매 2억 5천만원 이상(85제곱 이상) 400,000,000원 16,000,000원 1,600,000원 150,000원 13,000원 413,581원 610,000원 1,600,000원 0.04 0.002 0.002

 

각각 상황 별 , 부동산 금액 입력 시, 세율 및 세금을 정리하였다. 이제 위를 바탕으로 본격적으로 테스트 코드를 진행하자. 

 

ServiceTest를 진행하였다. 

package com.lnt.priros.service.soda;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;

import com.lnt.priros.model.entity.BondRate;
import com.lnt.priros.model.request.soda.CalcRequest;
import com.lnt.priros.service.BondRateService;
import com.lnt.priros.util.calc.rmra.ProvisionalEstimateCalcResponse;
import java.time.LocalDate;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
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.transaction.annotation.Transactional;

@SpringBootTest
@Transactional
@ExtendWith(MockitoExtension.class)
class SodaCalcServiceTest {

    @Autowired
    private SodaCalcService sodaCalcService;

    @MockBean
    private BondRateService bondRateService;

    private static final String CALC_TEP_ID = "0:0:0:0:0:0:0:1|Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36";

    @Test
    void 조정지역_주택1_6억이하_거래_감면혜택_없음_수도권_85제곱_이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(500_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(7_099_744)
        );
    }

    @Test
    void 비조정지역_주택1_6억이하_거래_감면혜택_없음_수도권_85제곱_이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(500_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(7_099_744)
        );
    }

    @Test
    void 조정지역_주택1_6억이하_거래_감면혜택_없음_수도권_85제곱_이상() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(500_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxRate()).isEqualTo(0.002f),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(8_099_744L)
        );
    }

    @Test
    void 비조정지역_주택1_6억이하_거래_감면혜택_없음_수도권_85제곱_이상() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(500_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxRate()).isEqualTo(0.002f),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(8_099_744L)
        );
    }

    @Test
    void 조정지역_주택1_6억초과_9억이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(900_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(2_700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(27_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(970_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(19_530_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(1_602_628),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(32_435_628)
        );
    }

    @Test
    void 비조정지역_주택1_6억초과_9억이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(900_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(2_700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(27_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(970_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(19_530_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(1_602_628),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(32_435_628)
        );
    }

    @Test
    void 조정지역_주택1_9억초과() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(1_000_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(3_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(30_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(2_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(2_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_040_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(21_700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(1_780_698),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(35_983_698L)
        );
    }

    @Test
    void 비조정지역_주택1_9억초과() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(1_000_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(3_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(30_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(2_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(2_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_040_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(21_700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(1_780_698),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(35_983_698L)
        );
    }


    @Test
    void 주택1_10억초과_20억원() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(6_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(60_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(4_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(4_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(71_464_395L)
        );
    }

    @Test
    void 조정대상지역_주택2_3억초과_6억이하_감면세혜택_없음_85제곱이상() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(2)
            .subjectUse("HEY2")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(2_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(40_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.08f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(3_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744L),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(46_599_744L)
        );
    }

    @Test
    void 비조정지역_주택2_6억이하_거래_감면혜택_없음_수도권_85제곱_이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEY1")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(500_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(7_099_744)
        );
    }

    @Test
    void 비조정지역_주택2_6억초과_9억이하_85제곱이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(900_000_000L)
            .subjectCnt(1)
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(2_700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(27_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(970_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(19_530_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(1_602_628),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(32_435_628)
        );
    }


    @Test
    void 주택2_조정대상지역_9억초과_감면세혜택_없음() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(2)
            .subjectUse("HEY2")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(8_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(160_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.08f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(12_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(185464_395L)
        );
    }

    @Test
    void 비조정_주택2_9억초과_85제곱이하() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(2)
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(6_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(60_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.03f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.003f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(4_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(4_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(71_464_395L)
        );
    }

    @Test
    void 조정대상지역_주택3_20억_감면세혜택_없음() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(3)
            .subjectUse("HEY3")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(8_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(240_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.12f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(20_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(273_464_395L)
        );
    }

    @Test
    void 비조정대상지역_주택3_20억_감면세혜택_없음() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(3)
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(8_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(160_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.08f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(12_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(185_464_395L)
        );
    }

    @Test
    void 주택4_조정대상지역_20억_감면세혜택_없음() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(4)
            .subjectUse("HEY4")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(true)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(8_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(240_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.12f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(20_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(273_464_395L)
        );
    }

    @Test
    void 주택4_비조정대상지역_20억_감면세혜택_없음() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(2_000_000_000L)
            .subjectCnt(4)
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .isAdjustedArea(false)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(8_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(240_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.12f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(12_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(1_540_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(43_400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(3_561_395),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(265_464_395L)
        );
    }

    @Test
    void 주택1_5억원이하_감면세혜택_생애최초_주택() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEF1")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(300_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(2_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(5_899_744)
        );
    }

    @Test
    void 주택1_5억원이하_감면세혜택_생애최초소형_주택() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEF3")
            .isFarmTaxApply(false)
            .sido("서울특별시")
            .gugun("강남구")
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(200_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(3_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxDisCount()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(3_799_744)
        );
    }

    @Test
    void 주택1_5억원이하_감면세혜택_출산가구_주택() {
        CalcRequest request = CalcRequest.builder()
            .tradePrice(500_000_000L)
            .subjectCnt(1)
            .subjectUse("HEP1")
            .isFarmTaxApply(true)
            .sido("서울특별시")
            .gugun("강남구")
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(5_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.01f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.001f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(5_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(1_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(690_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(9_100_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(746_744),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(2_599_744L)
        );
    }

    @Test
    void 주택_외_매매_천만원_이상_1억_3천만원_미만() {
        CalcRequest request = CalcRequest.builder()
            .subjectCnt(1)
            .sido("서울특별시")
            .gugun("도봉구")
            .subjectUse("ET")
            .isFarmTaxApply(true)
            .tradePrice(100_000_000L)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(400_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(4_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.04f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(200_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(70_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(700_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(57_442),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(5_090_442L)
        );
    }

    @Test
    void 비수도권_주택_외_매매_천만원_이상_1억_3천만원_미만() {
        CalcRequest request = CalcRequest.builder()
            .subjectCnt(1)
            .sido("충청남도")
            .gugun("아산시")
            .subjectUse("ET")
            .isFarmTaxApply(true)
            .tradePrice(100_000_000L)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(400_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(4_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.04f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(200_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(70_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(350_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(560_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(45_953L),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(5_078_953L)
        );
    }

    @Test
    void 주택_외_매매_1억_3천만원_이상_2억_5천만원_미만() {
        CalcRequest request = CalcRequest.builder()
            .subjectCnt(1)
            .sido("서울특별시")
            .gugun("도봉구")
            .subjectUse("ET")
            .isFarmTaxApply(true)
            .tradePrice(200_000_000L)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(800_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(8_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.04f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxRate()).isEqualTo(0.002f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(400_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(440_000),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(2_240_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(183_814),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(9_986_814)
        );
    }

    @Test
    void 수도권_주택_외_매매_2억_5천만원_이상() {
        CalcRequest request = CalcRequest.builder()
            .subjectCnt(1)
            .sido("서울특별시")
            .gugun("도봉구")
            .subjectUse("ET")
            .isFarmTaxApply(true)
            .tradePrice(400_000_000L)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(1_600_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(16_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.04f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxRate()).isEqualTo(0.002f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(800_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(610_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(5_600_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(459_535L),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(19_632_535L)
        );
    }

    @Test
    void 비_수도권_주택_외_매매_2억_5천만원_이상() {
        CalcRequest request = CalcRequest.builder()
            .subjectCnt(1)
            .sido("충청남도")
            .gugun("아산시")
            .subjectUse("ET")
            .isFarmTaxApply(true)
            .tradePrice(400_000_000L)
            .build();

        BondRate bondRate = BondRate.builder()
            .discountRate(8.20598d)
            .issueDate(LocalDate.of(2024, 4, 16))
            .build();

        given(bondRateService.selectBondRate(anyString())).willReturn(bondRate);

        ProvisionalEstimateCalcResponse provisionalEstimateCalcResponse = sodaCalcService.calcRMRA(CALC_TEP_ID, request, null);

        assertAll(
            () -> assertThat(provisionalEstimateCalcResponse.getEduTax()).isEqualTo(1_600_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTax()).isEqualTo(16_000_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxRate()).isEqualTo(0.04f),
            () -> assertThat(provisionalEstimateCalcResponse.getEduTaxRate()).isEqualTo(0.004f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTaxRate()).isEqualTo(0.002f),
            () -> assertThat(provisionalEstimateCalcResponse.getFarmTax()).isEqualTo(800_000),
            () -> assertThat(provisionalEstimateCalcResponse.getGoveStamp()).isEqualTo(150_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getRegTaxDisCount()).isEqualTo(0L),
            () -> assertThat(provisionalEstimateCalcResponse.getLegalPay()).isEqualTo(610_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getCourtStamp()).isEqualTo(13_000),
            () -> assertThat(provisionalEstimateCalcResponse.getBond()).isEqualTo(5_040_000L),
            () -> assertThat(provisionalEstimateCalcResponse.getBondPay()).isEqualTo(413_581L),
            () -> assertThat(provisionalEstimateCalcResponse.getTotal()).isEqualTo(19_586_581L)
        );
    }
}

 

위에서는 Boot Test와 Mockito 테스트를 함께 사용하고 있는 것을 볼 수 있다.

 

여기서 Mockito를 사용한 이유는, BondRate의 discountRate 값이 매일 초기화되어 변경되기 때문이다.

 

만약 Boot Test만으로 진행하면, 하루가 지나면서 discountRate 값이 바뀌어 테스트가 실패해버리는 문제가 발생한다.

 

이를 해결하기 위해, Mockito를 활용하여 discountRate 값을 임의로 고정하여, 테스트가 항상 일정한 결과를 내도록 만들었다.

 

그렇다면 왜 전체를 Mockito로 대체하지 않고 Boot Test를 함께 사용했는지 궁금할 수 있다.

 

그 이유는, Service 안의 다양한 상황별 로직이 Template Method 패턴을 사용하여 작성되어 있기 때문이다.

 

만약 모든 로직을 Mockito로 대체하려고 하면, 상황별로 매번 다른 반환 값을 정의해야 하고, 테스트 케이스마다 복잡도가 과도하게 높아진다.

 

따라서 이 경우, Boot Test를 통해 통합적으로 흐름을 검증하고, 변경 가능성이 있는 특정 값에 대해서만 Mockito로 제어하는 방식을 택했다.

 

결국, 테스트의 유지보수성과 생산성을 고려한 Trade-off 선택한 것이다.

 

해당 부분으로 통합테스트를 검증하였다.

 

class CalcBondTest {

    CalcBond calcBond = new CalcBond();

    // 1. 한국 시간대 설정
    ZoneId koreaZone = ZoneId.of("Asia/Seoul");

    // 2. 현재 시간(LocalDateTime)
    LocalDate now = LocalDate.now(koreaZone);

    @Test
    @DisplayName("매입용도가 주택 이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 2030만원인 경우")
    void 수도권_주택_2천만원_이상_5천만원_미만() {
        // 3. LocalDateTime → java.util.Date
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0, 0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 29_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(260_000);
        assertThat(resultBond.getBondPay()).isEqualTo(22_003);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 2030만원인 경우")
    void 비수도권_주택_2천만원_이상_5천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0, 0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 29_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(260_000);
        assertThat(resultBond.getBondPay()).isEqualTo(22_003);
    }

//    @Test
//    @DisplayName("매입용도가 토지면서 토지 위치가 수도권이며 시가 표준액이 70%기준 2030만원인 경우")
//    void metro_land_two_four() {
//        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0, 0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
//        long price = 29_000_000;
//        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.FM, "서울특별시", dto);
//        assertThat(resultBond.getBond()).isEqualTo(510_000);
//        assertThat(resultBond.getBondPay()).isEqualTo(43_161);
//    }

    @Test
    @DisplayName("매입 용도가 그 외 이면서 위치가 수도권이며 시가 표준액이 70%기준 2030만원인 경우")
    void 수도권_그_외_2천만원_이상_5천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0, 0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 29_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "충청남도 아산시", dto);

        assertThat(resultBond.getBond()).isEqualTo(160_000);
        assertThat(resultBond.getBondPay()).isEqualTo(13_541);
    }

    @Test
    @DisplayName("매입 용도가 그 외 이면서 위치가 비수도권이며 시가 표준액이 70%기준 2030만원인 경우")
    void 비수도권_그_외_2천만원_이상_5천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0, 0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 29_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "서울특별시", dto);

        assertThat(resultBond.getBond()).isEqualTo(200_000);
        assertThat(resultBond.getBondPay()).isEqualTo(16_926);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 5530만원인 경우")
    void 수도권_주택_5천만원_이상_1억원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 79_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(1_050_000);
        assertThat(resultBond.getBondPay()).isEqualTo(88_860);
    }



    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 5530만원인 경우")
    void 비수도권_주택_5천만원_이상_1억원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 79_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(770_000);
        assertThat(resultBond.getBondPay()).isEqualTo(65_164);
    }


//    @Test
//    @DisplayName("매입용도가 토지이면서 토지 위치가 수도권이며 시가 표준액이 70%기준 5530만원인 경우")
//    void metro_land_five_one_billion() {
//        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
//        long price = 79_000_000;
//        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.FM, "서울특별시", dto);
//        assertThat(resultBond.getBond()).isEqualTo(2_210_000);
//        assertThat(resultBond.getBondPay()).isEqualTo(187_030);
//    }
//
//    @Test
//    @DisplayName("매입용도가 토지이면서 토지 위치가 비수도권이며 시가 표준액이 70%기준 5530만원인 경우")
//    void no_metro_land_five_one_billion() {
//        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
//        long price = 79_000_000;
//        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.FM, "충청남도 아산시", dto);
//        assertThat(resultBond.getBond()).isEqualTo(1_940_000);
//        assertThat(resultBond.getBondPay()).isEqualTo(164_180);
//    }

   @Test
   @DisplayName("매입용도가 주택이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 1억4천만원인 경우")
   void 수도권_주택_1억_이상_1억_6천만원_미만() {
       BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
       long price = 200_000_000;
       ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
       assertThat(resultBond.getBond()).isEqualTo(2_940_000);
       assertThat(resultBond.getBondPay()).isEqualTo(248_809);
   }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 1억4천만원인 경우")
    void 비수도권_주택_1억_이상_1억_6천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 200_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(2_240_000);
        assertThat(resultBond.getBondPay()).isEqualTo(189_569);
    }

    @Test
    @DisplayName("매입용도가 그 외 이면서 위치가 수도권이며 시가 표준액이 70%기준 1억4천만원인 경우")
    void 수도권_그_외_1억_3천만원_이상_2억_5천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 200_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(2_240_000);
        assertThat(resultBond.getBondPay()).isEqualTo(189_569);
    }

    @Test
    @DisplayName("매입용도가 그 외 이면서 위치가 수도권이며 시가 표준액이 70%기준 1억4천만원인 경우")
    void 비수도권_그_외_1억_3천만원_이상_2억_5천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 200_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(1_960_000);
        assertThat(resultBond.getBondPay()).isEqualTo(165_872);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 2억3천백만원인 경우")
    void 수도권_주택_1억_6천만원_이상_2억_6천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 330_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(5_310_000);
        assertThat(resultBond.getBondPay()).isEqualTo(449_379);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 2억3천백만원인 경우")
    void 비수도권_주택_1억_6천만원_이상_2억_6천만원_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 330_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(4_160_000);
        assertThat(resultBond.getBondPay()).isEqualTo(352_056);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 3억1천5백만원인 경우")
    void 수도권_주택_2억_6천만원_이상_6억_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 450_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(8_190_000);
        assertThat(resultBond.getBondPay()).isEqualTo(693_110);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 3억1천5백만원인 경우")
    void 비수도권_주택_2억_6천만원_이상_6억_미만() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 450_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(6_620_000);
        assertThat(resultBond.getBondPay()).isEqualTo(560_243);
    }

    @Test
    @DisplayName("매입용도가 그 외이면서 위치가 수도권이며 시가 표준액이 70%기준 3억1천5백만원인 경우")
    void 수도권_그_외_2억_5천만원_이상() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 450_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(6_300_000);
        assertThat(resultBond.getBondPay()).isEqualTo(533_161);
    }

    @Test
    @DisplayName("매입용도가 그 외이면서 위치가 비수도권이며 시가 표준액이 70%기준 3억1천5백만원인 경우")
    void 비수도권_그_외_2억_5천만원_이상() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 450_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.ET, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(5_670_000);
        assertThat(resultBond.getBondPay()).isEqualTo(479_845);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 수도권이며 시가 표준액이 70%기준 7억인 경우")
    void 수도권_주택_6억_이상() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 1_000_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "서울특별시", dto);
        assertThat(resultBond.getBond()).isEqualTo(21_700_000);
        assertThat(resultBond.getBondPay()).isEqualTo(1_836_445);
    }

    @Test
    @DisplayName("매입용도가 주택이면서 주택 위치가 비수도권이며 시가 표준액이 70%기준 7억인 경우")
    void 비수도권_주택_6억_이상() {
        BondRateDto dto = new BondRateDto(1L, now, 8.46288d, 0d, 9178L, LocalDateTime.of(2025, 4, 15, 18, 0,0), LocalDateTime.of(2025, 4, 15, 18, 0, 0));
        long price = 1_000_000_000;
        ResultBond resultBond = calcBond.calc(price, CalcBond.BASIC_PRICE, EstateUseRMRA.HEF1, "충청남도 아산시", dto);
        assertThat(resultBond.getBond()).isEqualTo(18_200_000);
        assertThat(resultBond.getBondPay()).isEqualTo(1_540_244);
    }

}

 

순수 자바코드만을 가지고 단위 테스트 코드를 작성해주었습니다. 

 

import static org.assertj.core.api.Assertions.assertThat;


class CalcStampTest {

    @Test
    @DisplayName("EstateUseRMRA.HEY1인데 1억이하인 경우")
    void HEY1_one_billion_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(20_000_000L, EstateUseRMRA.HEY1);
        assertThat(calc.getGoveStamp()).isEqualTo(0L);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }

    @Test
    @DisplayName("EstateUseRMRA.HEY1인데 1억 초과인 경우")
    void HEY1_one_billion_over() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(110_000_000L, EstateUseRMRA.HEY1);
        assertThat(calc.getGoveStamp()).isEqualTo(150_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }

    @Test
    @DisplayName("EstateUseRMRA.FM 1천만원 초과 3천만원 이하인경우")
    void FM_one_three_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(20_000_000L, EstateUseRMRA.FM);
        assertThat(calc.getGoveStamp()).isEqualTo(20_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }


    @Test
    @DisplayName("EstateUseRMRA.FM 3천만원 초과 5천만원 이하인경우")
    void FM_three_five_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(40_000_000L, EstateUseRMRA.FM);
        assertThat(calc.getGoveStamp()).isEqualTo(40_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }

    @Test
    @DisplayName("EstateUseRMRA.FM 5천만원 초과 1억이하인 경우")
    void FM_five_one_billion_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(100_000_000L, EstateUseRMRA.FM);
        assertThat(calc.getGoveStamp()).isEqualTo(70_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }

    @Test
    @DisplayName("EstateUseRMRA.FM 1억초과 10억이하인경우")
    void FM_one_ten_billion_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(1_000_000_000L, EstateUseRMRA.FM);
        assertThat(calc.getGoveStamp()).isEqualTo(150_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }

    @Test
    @DisplayName("EstateUseRMRA.FM 10억 초과인경우")
    void FM_ten_over_stamp() {
        CalcStamp stamp = new CalcStamp();
        ResultStamp calc = stamp.calc(11_000_000_000L, EstateUseRMRA.FM);
        assertThat(calc.getGoveStamp()).isEqualTo(350_000);
        assertThat(calc.getCourtStamp()).isEqualTo(13_000);
    }
}

 

주택외에 대한 테스트 코드 케이스를 각각 작성해주었고, 이 코드가 내가 통합 테스트 코드에서 굳이 검증을 해주지 않은 이유입니다. 

왜냐면 단위테스트에서 검증이 끝났는데, 검증 과정을 반복할 이유는 없다고 판단 하였습니다. 

 

@Slf4j
class CalcTaxTest {

    @Test
    @DisplayName("1주택 3억이상 6억이하 4억 계산식")
    void four_billion_formula() {
        CalcTax tax = new CalcTax();

        ResultTax resultTax = tax.calculateTax(400_000_000, EstateUseRMRA.HEY1, true, false);

        assertThat(resultTax.getRegTax()).isEqualTo(4_000_000);
        assertThat(resultTax.getFarmTax()).isEqualTo(800_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0L);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0L);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getEduTax()).isEqualTo(400_000);
        assertThat(resultTax.getEduTaxRate()).isEqualTo(0.001f);
    }

    @Test
    @DisplayName("1주택 6억이상 9억이하 이상 계산식")
    void nine_billion_formula() {
        CalcTax tax = new CalcTax();

        ResultTax resultTax = tax.calculateTax(900_000_000, EstateUseRMRA.HEY1, true, false);

        assertThat(resultTax.getRegTax()).isEqualTo(27_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_700_000);
        assertThat(resultTax.getFarmTax()).isEqualTo(1_800_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
    }

    @Test
    @DisplayName("1주택 10억 이상 계산식")
    void formulaTest2() {
        CalcTax tax = new CalcTax();

        ResultTax resultTax = tax.calculateTax(1_000_000_000, EstateUseRMRA.HEY1, true, false);

        assertThat(resultTax.getRegTax()).isEqualTo(30_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(3_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
    }

    @Test
    @DisplayName("조정 대상지역 2주택 4억 계산식")
    void allw_two_houses_four_over_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(400_000_000, EstateUseRMRA.HEY2, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(32_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(1_600_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(2_400_000);
    }

    @Test
    @DisplayName("조정 대상지역 2주택 10억 계산식")
    void allow_two_houses_ten_over_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(1_000_000_000, EstateUseRMRA.HEY2, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(80_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(4_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(6_000_000);
    }

    @Test
    @DisplayName("비조정대상지역 2주택 6억이하 계산식")
    void no_allow_two_houses_six_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(400_000_000, EstateUseRMRA.HEN2, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(4_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(400_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(800_000);
    }

    @Test
    @DisplayName("비조정대상지역 2주택 6억초과 9억 이하 계산식")
    void no_allow_two_houses_nine_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(900_000_000, EstateUseRMRA.HEN2, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(27_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_700_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(18_000_00);
    }

    @Test
    @DisplayName("비조정대상지역 2주택 9억 초과 계산식")
    void no_allow_two_houses_nine_over_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(1_000_000_000, EstateUseRMRA.HEN2, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(30_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(3_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(2_000_000);
    }

    @Test
    @DisplayName("조정대상지역 3주택 6억 이하")
    void allow_three_houses_six_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEY3, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(60_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(5_000_000);
    }

    @Test
    @DisplayName("조정대상지역 3주택 9억이하")
    void allow_three_houses_nine_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(900_000_000, EstateUseRMRA.HEY3, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(108_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(3_600_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(9_000_000);
    }

    @Test
    @DisplayName("비조정대상지역 3주택 6억이하")
    void no_allow_three_houses_six_under_form() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEN3, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(40_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(3_000_000);
    }

    @Test
    @DisplayName("조정대상지역 4주택자")
    void allow_four_houses_six_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEY4, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(60_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(5_000_000);
    }

    @Test
    @DisplayName("비조정대상지역 4주택자")
    void no_allow_four_houses_six_under_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEN4, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(60_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(2_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
        assertThat(resultTax.getFarmTax()).isEqualTo(3_000_000);
    }

    @Test
    @DisplayName("생애최초 주택 5억")
    void first_buy_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEF1, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(3_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(300_000);
        assertThat(resultTax.getFarmTax()).isEqualTo(1_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(2_000_000);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("생애최초주택");
    }

    @Test
    @DisplayName("생애최초이지만 주택 가격이 13억 비대상자")
    void no_first_buy_but_over_money_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(1_300_000_000, EstateUseRMRA.HEF1, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(39_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(3_900_000);
        assertThat(resultTax.getFarmTax()).isEqualTo(2_600_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
    }

    @Test
    @DisplayName("출산가구 주택 가격이 5억")
    void child_birth_houses_five_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEP1, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(0);
        assertThat(resultTax.getEduTax()).isEqualTo(0);
        assertThat(resultTax.getFarmTax()).isEqualTo(1_000_000);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(5_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("출산가구");
    }

    @Test
    @DisplayName("출산가구지만 주택 가격이 13억 비대상자")
    void no_child_birth_houses_thirteen_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(1_300_000_000, EstateUseRMRA.HEP1, true, false);
        assertThat(resultTax.getRegTax()).isEqualTo(39_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(3_900_000);
        assertThat(resultTax.getFarmTax()).isEqualTo(2_600_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(0);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("");
    }

    @Test
    @DisplayName("생애최초소형주택 비수도권인 경우")
    void minum_first_buy_no_metrocity_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(300_000_000, EstateUseRMRA.HEF3, false, false);
        assertThat(resultTax.getRegTax()).isEqualTo(0);
        assertThat(resultTax.getEduTax()).isEqualTo(0);
        assertThat(resultTax.getFarmTax()).isEqualTo(0);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(3_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(600_000);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("생애최초소형주택");
    }

    @Test
    @DisplayName("생애최초소형주택 수도권인 경우")
    void minum_second_buy_metrocity_formula() {
        CalcTax tax = new CalcTax();
        ResultTax resultTax = tax.calculateTax(500_000_000, EstateUseRMRA.HEF3, false, true);
        assertThat(resultTax.getRegTax()).isEqualTo(2_000_000);
        assertThat(resultTax.getEduTax()).isEqualTo(200_000);
        assertThat(resultTax.getRegTaxDisCount()).isEqualTo(3_000_000);
        assertThat(resultTax.getFarmTaxDisCount()).isEqualTo(1_000_000);
        assertThat(resultTax.getReductionTaxName()).isEqualTo("생애최초소형주택");
        assertThat(resultTax.getFarmTax()).isEqualTo(0);
    }

}

 

 

테스트 코드로 작성하기 잘했다. 왜냐면 여러 케이스가 있고, 그와중에 여러가지 상황이 있는데 문제가 되는 케이스가 상당히 많아 테스트 코드를 기준으로 확인하면서 바꿔야하는 경우가 굉장히 많았습니다. 

내부 구현 로직은 보여줄 수 없고 각각의 테스트 케이스에 대해서만 보여주었습니다.

'TDD' 카테고리의 다른 글

다시 작성해보는 TDD RacingCar  (0) 2024.11.19
4단계 : racing car 리팩토링  (6) 2024.10.28
3단계 RacingCar TDD  (1) 2024.10.07
TDD 1단계 구현  (0) 2024.09.27