[Spring] 의존성 주입 테스트

msriver·2020년 6월 17일
0

Spring

목록 보기
3/16

교재 : 코드로 배우는 스프링 웹 프로젝트(개정판)
출판사 : 남가람북스
⚠이 포스팅은 책을 보고 공부한 내용을 정리한 책이므로 자세한 내용은 책을 참고할 것.

의존성 주입 테스트

이전 포스트에서도 적어 놓았듯이 스프링에서는 생성자를 이용한 주입, setter를 이용한 주입이 있다.
이번 예제에서는 Lombok을 이용해 setter 메서드를 자동으로 구현되도록 하고 스프링의 동작을 테스트 한다.

Lombok사용을 위한 설정

pom.xml에 Lombok, spring-test 추가 해야 한다.
모두 Maven Repository에서 검색을 통하여 찾을 수 있다.

  1. Lombok 추가
    버전은 최신버전이 아니지만 책의 예제대로 해보기 위해 1.18.0 버전을 사용
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.0</version>
		    <scope>provided</scope>
		</dependency>
  1. spring-test 추가
    버전에 쓰여있는 org.springframework.version은 spring의 버전과 동일하게 맞추기 위함.
<!-- https://mvnrepository.com/artifact/org.springframework/spring->test -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-test</artifactId>
		    <version>${org.springframework-version}</version>
		    <scope>test</scope>
		</dependency>
  1. Lombok 사용을 위한 Log4j 라이브러리 수정
<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>

아마 내 기준, 기존에 1.2.15버전으로 되어있었다. 이걸 1.2.17로 변경(안할 시 추후 Lombok사용 시 문제가 생길 수 있음)

의존성 주입 테스트를 위한 클래스 생성

Restaurant 클래스와 Chef 클래스를 작성할 것이다.
일반적으로 의존성 주입은 클래스가 아닌 인터페이스로 설계하는 것이 좋다고 한다.

Restaurant 클래스는 Chef 클래스를 주입받는 상황

package com.minsung.sample;

import org.springframework.stereotype.Component;

import lombok.Data;

@Component
@Data
public class Chef {
	
}
package com.minsung.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.Setter;

@Component
@Data
public class Restaurant {
	//@Setter는 lombok의 문법, 만약 사용하지 않을 경우 @Autowired만 써줌. 이건 Spring에서 주입하는 어노테이션
	//이클립스에서 의존주입성에 대한 어노테이션 표준을 만들기 위해 @Injection을 만듬. 표준
	@Setter(onMethod_ = @Autowired)
	private Chef chef;
}

@Data : Lombok의 setter을 생성하는 기능, 생성자와 toString()을 자동으로 생성하기위해 사용

@Component : 스프링에게 해당 클래스가 관리해야할 대상(Bean)임을 표시

@Setter : 자동으로 setChef()를 컴파일 시 생성.

@Setter의 onMethod속성 : 생성되는 setChef()에 @Autowired 어노테이션 추가

XML을 이용한 의존성 주입 설정

스프링은 클래스에서 객체를 생성하고 객체들의 의존성에 대한 처리 작업까지 내부에서 모든 것이 처리됨.

  • 스프링에서 관리되는 객체 = 빈, Bean

XML 말고도 java를 이용한 설정방식이 있지만 XML로만 쭉 진행할 것이다.

프로젝트 - src - webapp - WEB-INF - spring - root-context.xml

root-context.xml은 스프링 프레임워크에서 관리해야하는 객체(앞으로는 빈(Bean)이라고 표현한다.)를 설정하는 설정 파일이다.

root-context.xml파일 클릭 후 하단에 NameSpaces탭 클릭, 이후 context 항목 체크

다시 source탭을 선택하여 아래 코드 추가

<context:component-scan base-package="com.minsung.sample"></context:component-scan>

스프링이 동작하면서 생기는 일

  1. 스프링 프레임워크가 시작되면 먼저 스프링이 사용하는 메모리 영역을 만든다. 이를 컨텍스트(Context)라고 한다. 스프링에서는 ApplicationContext라는 이름의 객체가 만들어 진다.
  2. 스프링은 자신이 생성하고 관리해야 할 객체들에 대한 설정이 필요. 이 설정파일이 위 root-context.xml파일
  3. root-context.xml파일에 설정한 context:component-scan 태그는 base-package에 지정된 패키지를 스캔한다.
  4. 해당 패키지에 있는 클래스들 중에서 스프링이 사용하는 @Component 어노테이션이 존재하는 클래스의 인스턴스를 생성.
  5. 위 예시로 만든 클래스에서 Restaurant 클래스는 @Autowired 어노테이션을 통해 Chef객체가 필요하다는 것을 알린다. 이 알림을 본 스프링은 Chef 객체의 레퍼런스를 Restaurant 객체에 주입.

테스트 코드 작성해보기

src/test/java에 생성 (SampleTest.java)

package com.minsung.sample;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class SampleTest {
	@Setter(onMethod_ = @Autowired)
	private Restaurant restaurant;
	
	@Test
	public void testExist() {
		assertNotNull(restaurant);
		
		log.info(restaurant);
		log.info("-----------------------------");
		log.info(restaurant.getChef());
	}
}

테스트는 spring-test 모듈을 이용하여 스프링을 가동시키고 위 설명된 동작 순서들이 일어나게 한다. 이때 JUnit 버전은 4.10이상을 권한다.

  • @RunWith : 현재 테스트 코드가 스프링을 실행하는 역할을 할 것이라고 표시하는 것.
  • @ContextConfiguration : 문자열이나 클래스를 지정하여 사용한다. 필요한 객체들을 스프링 내에 객체로 등록한다.(스프링의 빈으로 등록된다) 내부에 사용하는 문자열은 'classpath:' 나 'file:' 을 이용할 수 있다.
  • @Log4j : Lombok을 이용해서 로그를 기록하는 Logger을 변수로 자동 생성해준다. 별도의 Logger 객체의 선언을 할 필요없이 이 어노테이션을 작성해준다면 사용이 가능하다. 프로젝트를 Spring Legacy Project로 만든 경우 기본적으로 Log4j와 해당 설정이 완료된다. 'src/main/resources' , 'src/test/resources'에 설정파일이 존재함.
  • @Autowired : 스프링한테 내가 필요한 객체를 달라고 알리는 표시
  • @Test : JUnit(단위테스트용)에서 테스트 대상을 표시.
  • AssertNotNull() : restaurant변수가 null이 아니어야만 테스트가 성공한다는 것을 의미한다.

실행은 Run as > Junit Test

실행결과에서 주목해야 할 부분

  1. 나는 Restaurant 객체를 생성한적이 없지만 (new Restaurant() 사용 x) 객체가 만들어 졌다.
    이는 관리가 필요한 객체(빈)을 어노테이션 등을 이용하여 스프링이 생성,관리를 해주기 때문이다. = 일종의 컨테이너, 팩토리
  2. Restaurant객체는 @Data 어노테이션을 통해 여러 메서드들이 만들어졌다.(getter/setter, 생성자, hasHash() 등등)
    @Data는 Lombok을 이용하는 방법, 작성된 setter에 @Autowired 어노테이션을 추가함으로써 의존성 주입
  3. Restaurant 객체의 인스턴스 변수인 chef 또한 Chef타입의 객체가 주입되어 있다는 것.
profile
NOBODY

0개의 댓글