교재 학습 - 스프링 부트를 활용한 마이크로 서비스 개발 (2)

Kyu0·2023년 2월 20일
0

도입 🎬

본격적으로 프로젝트 개발에 도입하는 챕터입니다.

웹 어플리케이션에서 주로 활용하는 아키텍처인 3계층 아키텍처(Presentation, Application, Data)를 활용하여 개발을 진행합니다.


교재 학습 (Chapter 3. 3계층 스프링 부트 애플리케이션) 📚

1. Kotest 테스트 코드 작성 시 컴파일 오류

@MockkBean, @Autowired 와 같은 DI 관련 어노테이션을 사용한 테스트 코드를 작성한 뒤, 컴파일 오류가 나는 것을 확인할 수 있었습니다. 아래는 해당 코드입니다.

// MultiplicationControllerTest.kt

@WebMvcTest(MultiplicationController::class)
class MultiplicationControllerTest : BehaviorSpec({
	@Autowired //! error : This annotation is not applicable to target 'local variable
	private lateinit var multiplicationService: MultiplicationService
    
    @MockkBean //! error : This annotation is not applicable to target 'local variable
    private lateinit var mvc: MockMvc
    
    given("get /multiplications/random 테스트") {
    	//... 생략
    }
}) {

}

@MockkBean, @Autowired 어노테이션이 적용된 변수들이 클래스의 필드들이 지역 변수로 선언이 되어있기 때문에 적용되지 않는다는 메시지였습니다.

Kotlin 에서 사용되는 문법인 class 자식클래스(생성자) : 부모클래스(생성자) 에 대해서 잘 몰랐기 때문에 실수를 한 것입니다.

그래서 아래와 같이 코드를 수정했습니다.

// MultiplicationControllerTest.kt

@WebMvcTest(MultiplicationController::class)
class MultiplicationControllerTest : BehaviorSpec() {

	@Autowired
    private lateinit var multiplicationService: MultiplicationService
    
    @MockkBean
    private lateinit var mvc: MockMvc
    
    init {
    	given("get /multiplications/random 테스트") {
        	//...생략
        }
    }
}

그럼에도 불구하고 테스트 코드를 실행하면 multiplicationService 가 초기화되지 않았다는 오류 메시지를 출력하며 테스트가 정상적으로 실행되지 않았습니다.

BehaviorSpec 클래스에서는 테스트 코드 실행이 init 블록을 수행하는 단계에서 이뤄지기 때문에 의존성 주입보다 테스트 코드를 수행하는 단계가 먼저 이뤄져서 아직 의존성이 주입되지 않은 상태에서 테스트 코드를 수행하기 때문에 해당 오류가 발생한 것이었다.

이를 인식하고 필드 선언을 자식 클래스인 MultiplicationControllerTest에 선언하도록 수정했습니다.

@WebMvcTest(MultiplicationController::class)
class MultiplicationControllerTest(
	@Autowired
    private val multiplicationService: MultiplicationService,
    @MockkBean
    private val mvc: MockMvc
) : BehaviorSpec() {
	init {
    	give("get /multiplications/random 테스트") {
        	//...생략
        }
    }
}

그랬더니 이번엔 MultiplicationControllerTest 클래스의 기본 생성자를 제공하지 않았다는 런타임 오류가 발생했습니다.

이는 간단하게 Spring Boot 프로젝트에 no-arg 플러그인을 적용해서 해결했습니다.

plugins {
	id("org.springframework.boot") version "3.0.2"
	id("io.spring.dependency-management") version "1.1.0"
	id("org.jetbrains.kotlin.plugin.noarg") version "1.7.22" // 플러그인 적용
	kotlin("jvm") version "1.7.22"
	kotlin("plugin.spring") version "1.7.22"
}

아래는 최종적으로 오류를 해결한 코드를 디컴파일한 코드 중 일부입니다.

// MultiplicationControllerTest.java, 디컴파일한 Java 코드

    public MultiplicationControllerTest(@NotNull final MultiplicationService multiplicationService, @Autowired @NotNull final MockMvc mvc) {
        Intrinsics.checkNotNullParameter((Object)multiplicationService, "multiplicationService");
        Intrinsics.checkNotNullParameter((Object)mvc, "mvc");
        super((Function1)null, 1, (DefaultConstructorMarker)null);
        // 필드가 제대로 초기화 됐음을 볼 수 있습니다.
        this.multiplicationService = multiplicationService;
        this.mvc = mvc;
        JacksonTester.initFields((Object)this, new ObjectMapper());
        // 필드 초기화 후 테스트 수행
        this.given("get /multiplications/random \ud14c\uc2a4\ud2b8", (Function2)new MultiplicationControllerTest.MultiplicationControllerTest$1(this, (Continuation)null));
    }

학습 결과 및 마무리 👏🏻

이번 챕터에서는 Kotest 에 대한 지식을 많이 습득한 것 같습니다.

  1. Kotest 를 이용한 테스트 코드에서, 생성자 메소드를 활용한 방식과 init 메소드를 활용한 방식을 알게 됐습니다.
  2. Kotlin 은 Java 와 달리 기본 생성자 (매개변수가 없는 생성자)를 자동으로 생성하지 않는다는 사실을 알게 됐습니다.

예제 프로젝트 깃허브 주소 : https://github.com/Kyu0/microservies-book/tree/82247d730e437d3fbb2c505b8d84428d72f0a057

잘못된 내용이나 오타 지적 언제나 환영입니다.

profile
개발자

0개의 댓글