이 section에서는 Spring Boot에 대해 자세히 설명합니다. 여기에서 사용하고 customize 할 수 있는 주요 기능에 대해 알아볼 수 있습니다. 아직 시작하지 않은 경우 "getting-started.html" 및 "using-spring-boot.html" section을 통해 기본 지식을 잘 이해할 수 있습니다.

1. Logging

Spring Boot는 모든 내부 logging에 Commons Logging을 사용하지만 기본 로그 구현은 오픈되어 있습니다 Java Util Logging, Log4J2, and Logback에 대한 기본 구성이 제공됩니다.. 각각의 경우에 logger는 optional file output도 사용 가능한 console output을 사용하도록 사전 구성되어 있습니다.

기본적으로 "`Starters`"를 사용하면 Logback이 logging에 사용됩니다. Java Util Logging, Commons Logging, Log4J 또는 SLF4J를 사용하는 종속 library가 모두 올바르게 작동하는지 확인하기 위해 적절한 logback routing도 포함됩니다.

Java에 사용할 수 있는 logging framework가 많이 있습니다. 위 목록이 헷갈리더라도 걱정하지 마세요. 일반적으로 logging dependencies을 변경할 필요가 없으며 Spring Boot 기본값이 잘 작동합니다.
application을 servlet container 또는 application server에 배포할 때 Java Util Logging API를 통해 수행된 logging은 application의 log로 route 되지 않습니다. 이렇게 하면 container 또는 container에 배포된 다른 application에서 수행한 logging이 application의 log에 표시되지 않습니다.

1.1. Log Format

Spring Boot의 default log output은 다음 예제와 유사합니다:

2019-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2019-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

다음 항목이 출력됩니다:

  • Date and Time: Millisecond의 정밀도와 쉽게 정렬 가능.

  • Log Level: ERROR, WARN, INFO, DEBUG, or TRACE.

  • Process ID.

  • 실제 log message의 시작을 구분하는 --- 구분자.

  • Thread name: 대괄호로 묶여 있습니다. (console output을 위해 잘릴 수 있음)

  • Logger name: 일반적으로 source class name. (종종 축약됨)

  • The log message.

Logback은 FATAL level을 가지고 있지 않습니다. 이는 ERROR 로 맵핑됩니다.

1.2. Console Output

default log configuration은 작성될 때 console에 message를 표시합니다. default로 ERROR-level, WARN-level, 그리고 INFO-level message가 기록됩니다. by starting your application with a --debug flag로 application을 시작하여 “debug” mode 를 활성화할 수도 있습니다.

$ java -jar myapp.jar --debug
application.properties 에서 debug=true 를 지정할 수도 있습니다.

debug mode가 활성화되면 더 많은 정보를 출력하도록 core logger (embedded container, Hibernate 및 Spring Boot) 선택이 구성됩니다. debug mode를 활성화해도 DEBUG level로 모든 message를 기록하도록 application이 구성되지는 않습니다.

또는 --trace flag (또는 trace=true in your application.properties) 로 application을 시작하여 “trace” mode를 활성화할 수 있습니다. 이렇게 하면 선택한 core logger (embedded container, Hibernate schema generation 및 전체 Spring Boot portfolio)에 대한 trace logging이 가능합니다.

1.2.1. Color-coded Output

termintal이 ANSI를 지원하는 경우 가독성을 높이기 위해 색상 출력이 사용됩니다. spring.output.ansi.enabledsupported value 으로 설정하여 auto-detection을 override 할 수 있습니다..

색 구분은 %clr conversion word를 사용하여 구성됩니다. 가장 간단한 형식으로 converter는 다음 예와 같이 log level에 따라 출력에 색상을 지정합니다.:

%clr(%5p)

아래 table은 색상에 대한 log level mapping을 설명합니다.:

Level Color

FATAL

Red

ERROR

Red

WARN

Yellow

INFO

Green

DEBUG

Green

TRACE

Green

또는 변환 옵션을 제공하여 사용해야 하는 색상 또는 스타일을 지정할 수 있습니다. 예를 들어 text를 노란색으로 만들려면 다음 설정을 사용합니다:

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

The following colors and styles are supported:

  • blue

  • cyan

  • faint

  • green

  • magenta

  • red

  • yellow

1.3. File Output

기본적으로 Spring Boot log는 console 만 log를 처리하고 log file을 작성하지 않습니다. 만약 console 출력 외에 log file을 남기길 원한다면 configprop:logging.file.name[] 또는 configprop:logging.file.path[] property를 (예를 들면 application.properties 에서) 설정해야 합니다.

아래 테이블은 logging.* properties를 함께 사용할 수 있는 방법을 보여줍니다.:

Table 1. Logging properties
configprop:logging.file.name[] configprop:logging.file.path[] Example Description

(none)

(none)

Console only logging.

Specific file

(none)

my.log

지정된 log file에 기록합니다. 이름은 정확한 위치이거나 또는 현재 directory에 상대적일 수 있습니다.

(none)

Specific directory

/var/log

지정된 directory에 spring.log 를 기록합니다. 이름은 정확한 위치이거나 또는 현재 directory에 상대적일 수 있습니다

Log file은 10MB에 도달하면 rotate 되며 console output과 마찬가지로 ERROR-level, WARN-level 및 INFO-level message가 default로 기록됩니다.

Logging properties는 실제 logging infrastructure에 독립적입니다. 결과적으로 특정 configuration key들은(logback을 위한 logback.configurationFile 같은) Spring Boot에서 관리되지 않습니다.

1.4. File Rotation

만약 logback을 사용하는 경우 application.properties 또는 application.yaml file에서 log rotation setting을 자세하게 할 수 있습니다. 다른 모든 logging system의 경우 직접 rotation setting을 구성해야 합니다. (예를 들면 Log4j2를 사용하는 경우 log4j.xml file을 추가하여 사용)

다음 rotation policy properties가 지원됩니다.:

Name Description

configprop:logging.logback.rollingpolicy.file-name-pattern[]

log archive를 만드는데 사용되는 filename pattern입니다.

configprop:logging.logback.rollingpolicy.clean-history-on-start[]

application이 시작될 때 log archive cleanup이 수행되어야 하는 경우

configprop:logging.logback.rollingpolicy.max-file-size[]

archive 되기 전 log file의 maximum size

configprop:logging.logback.rollingpolicy.total-size-cap[]

log archive를 삭제할 수 있는 maximum amount

configprop:logging.logback.rollingpolicy.max-history[]

log archive 보관 일 수 (default : 7)

1.5. Log Levels

모든 지원되는 logging system은 TRACE, DEBUG, INFO, WARN, ERROR, FATAL 또는 OFF 중 하나를 levellogging.level.<logger-name>=<level> 을 사용하여 logger level을 Spring Environment 에 (예를 들면 application.properties 에) 설정할 수 있습니다. logging.level.root 를 사용하여 root logger를 설정할 수 있습니다.

아래 예제는 application.properties 의 잠재적 logging 설정을 보여줍니다:

Properties
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
Yaml
logging:
  level:
    root: "warn"
    org.springframework.web: "debug"
    org.hibernate: "error"

environment variable을 사용하여 logging level을 설정할 수도 있습니다. 예를 들어 LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUGorg.springframework.webDEBUG 로 설정합니다.

위의 접근 방식은 package level logging에 대해서만 적용됩니다. relaxed binding은 언제나 environment variable을 소문자로 변환하기 때문이 이 방식으로 개별 class에 대한 logging을 설정할 수 없습니다. 만약 class에 대해 loggin을 설정하고자 하는 경우 the SPRING_APPLICATION_JSON variable을 사용할 수 있습니다.

1.6. Log Groups

관련 logger를 함께 그룹화하여 모두 동시에 구성할 수 있으면 유용합니다. 예를 들어 일반적으로 모든 Tomcat 관련 logger의 logging level을 변경할 수 있지만 최상위 패키지를 쉽게 기억할 수 없습니다.

이를 돕기 위해 Spring Environment 를 사용하면 logging group을 정의할 수 있습니다. 예를 들어 “tomcat” group을 application.properties 에 추가하여 정의하는 방법은 다음과 같습니다:

logging:
  group:
    tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"

일단 정의되면 한 줄로 모든 그룹에 있는 모든 logger의 level을 변경할 수 있습니다:

logging:
  level:
    tomcat: "trace"

Spring Boot에는 즉시 사용할 수 있는 다음과 같은 사전 정의된 logging group이 포함되어 있습니다:

Name Loggers

web

org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans

sql

org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

1.7. Using a Log Shutdown Hook

application 종료 시 loggin resource를 해제하기 위해 JVM 종료 시 log system cleanup을 trigger 하는 shutdown hook이 제공됩니다. 이 shutdown hook은 application이 war 파일로 배포되지 않는 한 자동으로 등록됩니다. application에 복잡한 context hierarchy가 있는 경우 요구 조건이 충족되지 않아 shutdown hook이 동작하지 않을 수 있습니다. 이런 경우 shutdown hook을 비활성화하고 logging system에 직접 처리하는 옵션을 사용합니다. 예를 들어 logback은 context selectors를 제공하여 각 logger를 자체 context에서 생성할 수 있습니다. configprop:logging.register-shutdown-hook[] property를 사용하여 shutdown hook를 비활성화 할 수 있습니다. false 로 설정하면 등록이 비활성화 됩니다. application.properties 또는 application.yaml 파일에서 property를 설정할 수 있습니다.

logging:
  register-shutdown-hook: false

1.8. Custom Log Configuration

다양한 loggin system은 classpath에 적절한 library를 포함하여 활성화할 수 있으며 classpath의 root 또는 Spring Environment property: configprop:logging.config[] 에 지정된 위치에 적절한 configuration file을 제공하여 추가로 customize 할 수 있습니다.

org.springframework.boot.logging.LoggingSystem system property를 사용하여 Spring Boot가 특정 logging system을 사용하도록 강제할 수 있습니다. 값은 LoggingSystem 구현의 명확한 class name이어야 합니다. none 값을 사용하여 Spring Boot의 Logging configuration을 완전히 비활성화할 수도 있습니다.

logging은 ApplicationContext 가 만들어지기 이전 에 초기화되기 때문에 Spring @Configuration file의 @PropertySources 에서 logging을 설정할 수 없습니다. logging system을 변경하거나 완전히 비활성화하는 유일한 방법은 System properties를 이용하는 것입니다.

logging system에 따라 다음 file이 load 됩니다:

Logging System Customization

Logback

logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy

Log4j2

log4j2-spring.xml or log4j2.xml

JDK (Java Util Logging)

logging.properties

가능한 경우 logging configuration에 -spring variants 을 사용하는 것이 좋습니다. (예를 들면 logback.xml 대신 logback-spring.xml ). standard configuration location을 사용하는 경우 Spring은 log initialization을 완전히 제어할 수 없습니다.
Java Util Logging에 'executable jar’에서 실행할 때 문제를 일으키는 classloading issue가 있습니다. 가능하면 'executable jar’에서 실행할 때 피하는 것이 좋습니다.

customization을 돕기 위해 다음 표에 설명된 대로 일부 다른 properties가 Spring Environment 에서 System properties로 전달됩니다.

Spring Environment System Property Comments

configprop:logging.exception-conversion-word[]

LOG_EXCEPTION_CONVERSION_WORD

The conversion word used when logging exceptions.

configprop:logging.file.name[]

LOG_FILE

If defined, it is used in the default log configuration.

configprop:logging.file.path[]

LOG_PATH

If defined, it is used in the default log configuration.

configprop:logging.pattern.console[]

CONSOLE_LOG_PATTERN

The log pattern to use on the console (stdout).

configprop:logging.pattern.dateformat[]

LOG_DATEFORMAT_PATTERN

Appender pattern for log date format.

configprop:logging.charset.console[]

CONSOLE_LOG_CHARSET

The charset to use for console logging.

configprop:logging.pattern.file[]

FILE_LOG_PATTERN

The log pattern to use in a file (if LOG_FILE is enabled).

configprop:logging.charset.file[]

FILE_LOG_CHARSET

The charset to use for file logging (if LOG_FILE is enabled).

configprop:logging.pattern.level[]

LOG_LEVEL_PATTERN

The format to use when rendering the log level (default %5p).

PID

PID

The current process ID (discovered if possible and when not already defined as an OS environment variable).

logback을 사용하는 경우 다음 properties도 전달됩니다:

Spring Environment System Property Comments

configprop:logging.logback.rollingpolicy.file-name-pattern[]

LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN

Pattern for rolled-over log file names (default ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz).

configprop:logging.logback.rollingpolicy.clean-history-on-start[]

LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START

Whether to clean the archive log files on startup.

configprop:logging.logback.rollingpolicy.max-file-size[]

LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE

Maximum log file size.

configprop:logging.logback.rollingpolicy.total-size-cap[]

LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP

Total size of log backups to be kept.

configprop:logging.logback.rollingpolicy.max-history[]

LOGBACK_ROLLINGPOLICY_MAX_HISTORY

Maximum number of archive log files to keep.

지원되는 모든 logging system은 configuration file을 parsing 할 때 system properties를 참조할 수 있습니다. `spring-boot.jar`의 default configuration을 참조하세요:

logging property에 placeholder를 사용하려면 기본 framework의 구문이 아닌 Spring Boot’s syntax 를 사용해야 합니다. 특히 Logback을 사용하는 경우 property name과 default value 사이에 : 구분 기호로 사용하고 :- 를 사용하지 말아야 합니다.

LOG_LEVEL_PATTERN (또는 logback의 logging.pattern.level ) 만 overriding 하여 MDC 및 다른 ad-hoc content를 log line에 추가할 수 있습니다. 예를 들어 logging.pattern.level=user:%X{user} %5p, 를 사용하는 경우 default log format에는 다음 예제와 같이 "user"에 대한 MDC 항목이 포함됩니다. (있는 경우)

2019-08-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

1.9. Logback Extensions

Spring Boot에는 advanced configuration에 도움이 되는 Logback에 대한 여러 extension이 포함되어 있습니다. logback-spring.xml configuration file에서 이러한 extension을 사용할 수 있습니다.

standard logback.xml configuration file은 너무 일찍 로드되기 때문에 이 file에서 extension을 사용할 수 없습니다. logback-spring.xml 을 사용하거나 또는 configprop:logging.config[] property를 정의해야 합니다.
extension은 Logback의 configuration scanning과 함께 사용할 수 없습니다. 만약 이렇게 하려고 하면 configuration file을 변경하면 다음과 유사한 오류가 발생합니다.
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

1.9.1. Profile-specific Configuration

<springProfile> 태그는 active Spring Profile에 기반한 configuration section을 선택적으로 포함하거나 제외할 수 있습니다. Profile section은 <configuration> 요소 내 모든 위치에서 지원됩니다. name attribute를 사용하여 대상 configuration profile을 지정할 수 있습니다. <springProfile> tag는 profile name(예를 들어 staging ) 또는 profile expression을 포함할 수 있습니다. profile expression은 좀 더 복잡한 profile logic을 표현할 수 있습니다. (예: production & (eu-central | eu-west) ) 자세한 내용은 reference guide를 확인하세요. 다음 목록은 세 가지 sample profile을 보여줍니다.

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

1.9.2. Environment Properties

<springProperty> tag를 사용하면 logback 내에서 사용할 수 있도록 Spring Environment 의 properties를 노출할 수 있습니다. 이렇게 하면 Logback configuration에서 application.properties file의 값에 접근하려는 경우 유용할 수 있습니다. tag는 logback standard <property> tag와 유사한 방식으로 동작합니다. 그러나 직접 value 를 지정하는 대신 property의 source 를 지정합니다( Environment 로 부터). property를 local scope 이외의 다른 곳에 저장해야 하는 경우 scope attribute를 사용할 수 있습니다. fallback value가 필요한 경우 ( Environment 에서 property를 설정하지 않은 경우) defaultValue attribute를 사용할 수 있습니다. 다음 예에서는 Logback 내에서 사용할 properties를 노출하는 방법을 보여줍니다.

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>
source 는 kebab case(예: my.property-name)로 지정해야 합니다. 그러나 완화된 규칙을 사용하여 property를 Environment 에 추가할 수 있습니다.

2. Testing

Spring Boot는 application을 테스트 할 때 도움이 되는 여러 utility와 annotation을 제공합니다. 테스트 지원은 두 개의 module로 제공됩니다: spring-boot-test 는 핵심 항목을 포함하고, spring-boot-test-autoconfigure 는 테스트를 위한 autoconfigure를 지원합니다.

대부분의 개발자는 Spring Boot test module과 JUnit Jupiter, AssertJ, Hamcrest 및 기타 여러 유용한 라이브러리를 가져오는 spring-boot-starter-test "`Starter`"를 사용합니다.

JUnit4를 사용하는 테스트가 있는 경우 JUnit 5의 vintage engine을 사용하여 실행할 수 있습니다. vintage engine을 사용하려면 junit-vintage-engine dependency를 아래 예제와 같이 추가하세요:

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

spring-boot-starter-test 에 포함된 org.hamcrest:hamcrest 를 사용하며 hamcrest-core 는 제외됩니다. (hamcrest에 통합되었음)

2.1. Test Scope Dependencies

The spring-boot-starter-test “Starter” 는 (test scope 에서) 아래와 같은 라이브러리가 포함됩니다:

  • JUnit 5: Java applications 단위 테스트를 위한 사실상 표준

  • Spring Test & Spring Boot Test: Spring Boot applications을 위한 유틸리티 및 통합 테스트 지원.

  • AssertJ: A fluent assertion library.

  • Hamcrest: matcher objects의 라이브러리 (constraints 또는 predicates로 알려진).

  • Mockito: A Java mocking framework.

  • JSONassert: An assertion library for JSON.

  • JsonPath: XPath for JSON.

일반적으로 이러한 공통 라이브러리는 테스트를 작성할 때 유용합니다. 이러한 라이브러리가 필요하지 않으면 자체적으로 테스트 dependency를 추가하면 됩니다.

2.2. Testing Spring Applications

dependency injection의 주요 장점 중 하나는 단위 테스트하기 쉽게 코드를 만들 수 있다는 것입니다. Spring을 사용하지 않더라도 new operator를 사용하여 object를 인스턴스화 할 수 있습니다. 실제 dependency 대신 mock object 를 사용할 수도 있습니다.

종종 단위 테스트를 뛰어넘어 통합 테스트를 해야합니다. (Spring ApplicationContext 과 함께) application을 배포하거나 다른 infrastructure와 연결할 필요 없이 통합 테스트를 수행할 수 있는 것이 유용합니다.

Spring Framework에는 이러한 통합 테스트를 위한 전용 test module이 포함되어 있습니다. Spring Framework인 org.springframework:spring-test 를 바로 dependency 설정하거나 spring-boot-starter-test “Starter” 를 통해 가져올 수 있습니다.

spring-test module을 이전에 사용하지 않았다면 Spring Framework reference의 관련 section을 읽는 것으로 시작해야 합니다.

2.3. Testing Spring Boot Applications

Spring Boot application은 Spring ApplicationContext 이므로 vanilla Spring contenxt에서 일반적인 테스트를 하는 것보다 특별한 것은 없습니다.

Spring Boot의 외부 properties, logging 및 다른 기능은 기본적으로 SpringApplication 을 사용하여 생성하는 경우에만 context에 처리됩니다.

Spring Boot는 Spring Boot 기능이 필요할 때 표준 spring-test @ContextConfiguration annotation의 대안으로 사용할 수 있는 @SpringBootTest annotation을 제공합니다. 이 annotation은 SpringApplication 을 통해 테스트에 사용된 ApplicationContext 를 생성 하는 방식으로 동작합니다. @SpringBootTest 외에 더 구체적인 slice test를 위해 여러 개의 다른 annotation도 제공됩니다.

JUnit 4를 사용하는 경우 @RunWith(SpringRunner.class) 를 테스트에 추가해야하는 것을 잊지 마세요. 그렇지 않으면 annotation이 무시됩니다. JUnit 5를 사용하는 경우 @SpringBootTest 와 다른 @…Test annotation이 이미 선언하고 있으므로 @ExtendWith(SpringExtension.class) 를 추가할 필요가 없습니다.

기본적으로 @SpringBootTest 는 server를 시작하지 않습니다. @SpringBootTestwebEnvironment attribute를 사용하여 테스트 수행 방법을 구체화 할 수 있습니다:

  • MOCK(Default) : web ApplicationContext 을 로드하고 mock web environment을 제공합니다. 이 annotation을 사용할 때 embeded server가 시작되지 않습니다. classpath에 web environment가 없는 경우, 이 mode는 web이 아닌 일반 ApplicationContext 를 생성합니다. @AutoConfigureMockMvc 또는 @AutoConfigureWebTestClient와 함께 web application의 mock-based 테스트를 위해 사용할 수 있습니다.

  • RANDOM_PORT: WebServerApplicationContext 를 로드하고 실제 web environment를 제공합니다. embedded server가 시작되고 random port를 사용합니다.

  • DEFINED_PORT: WebServerApplicationContext 를 로드하고 실제 web environment를 제공합니다. embedded server가 (application.properties 에) 정의된 port 또는 default port인 8080 으로 시작됩니다.

  • NONE: SpringApplication 을 사용하여 ApplicationContext 를 로드하지만 web environment (mock or otherwise)는 전혀 제공하지 않습니다.

테스트가 @Transactional 인 경우 default로 각 테스트 method의 종료 시 transaction을 roll back합니다. 그러나 RANDOM_PORT 또는 DEFINED_PORT 와 함께 사용시 암시적으로 실제 servlet 환경을 제공하므로, HTTP client와 server는 별도의 thread에서 실행되므로 별도의 transcation에서 실행됩니다. 이 경우 server에서 시작된 transcation은 roll back 되지 않습니다.
webEnvironment = WebEnvironment.RANDOM_PORT 와 함께 @SpringBootTest 사용 시 application이 management server에 대해 다른 port를 사용하는 경우 별도의 random port로 management server를 시작합니다.

2.3.1. Detecting Web Application Type

Spring MVC를 사용할 수 있는 경우 일반 MVC 기반 application context가 구성됩니다. Spring WebFlux만 있는 경우 이를 감지하고 WebFlux 기반 application context를 구성합니다.

만약 둘다 있으면 Spring MVC가 우선합니다. 이 시나리오에서 reactive web application을 테스트하려면 configprop:spring.main.web-application-type[] property를 설정해야 합니다.

@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests { ... }

2.3.2. Detecting Test Configuration

Spring Test Framework에 익숙하다면 Spring @Configuration 를 로드하기 위해 @ContextConfiguration(classes=…​) 를 사용하는데 익숙할 수 있습니다. 또는 테스트내에서 중첩 @Configuration class를 자주 사용했을 수 있습니다.

Spring Boot application을 테스트할 때 이는 종종 필요하지 않습니다. Spring Boot의 @*Test annotation은 주요 configuration을 정의하지 않아도 자동으로 검색합니다.

검색 알고리즘은 @SpringBootApplication 또는 @SpringBootConfiguration annotation이 달린 class를 테스트가 포함된 package에서 동작합니다. 코드를 합리적으로 구성하기만 하면 주요 구성이 대개 검색됩니다.

test annotation을 사용하여 application의 특정 부분을 테스트하는 경우 main method의 application class에 특정 영역에 특정 configuration 설정을 추가하지 않도록 해야합니다.

@SpringBootApplication 의 component scan configuration은 slicing이 예상대로 작동하는지 확인하는데 사용되는 exclude filter를 정의합니다. @SpringBootApplication annotation을 사용한 class에 @ComponentScan 을 직접 사용하는 경우 해당 filter는 비활성화 됩니다. slicing을 사용하는 경우 slice를 다시 정의해야 합니다.

primary configuration을 customize하려는 경우 중첩된 @TestConfiguration class를 사용할 수 있습니다. application의 primary configuration 대신 사용되는 중첩된 @Configuration class와 달리 중첩된 @TestConfiguration 는 application의 primary configuration에 추가로 적용됩니다.

Spring의 test framework는 test간 application context를 캐시합니다. 따라서 테스트가 동일한 configuration을 공유하는 한 (검색 방법에 관계 없이) 잠재적으로 시간이 많이 걸리는 context loading도 한 번만 발생합니다.

2.3.3. Excluding Test Configuration

application에서 component scan을 사용하는 경우 (예: @SpringBootApplication 또는 @ComponentScan 를 사용하는 경우) 특정 테스트용으로만 생성한 top-level copnfiguration class가 실수로 모든 곳에서 선택될 수 있습니다.

앞서 살펴본 것처럼 @TestConfiguration 은 test의 inner class에서 primary configuration을 customize 하는데 사용할 수 있습니다. top-level class에 배치될 떄 @TestConfigurationsrc/test/java 의 class를 검색으로 선택할 수 없음을 나타냅니다. 그런 다음 아래 예제와 같이 필요한 위치의 해당 class를 명시적으로 import 할 수 있습니다.

@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {

    @Test
    void exampleTest() {
        ...
    }

}
만약 @ComponentScan 를 직접 사용한다면 (즉 @SpringBootApplication 을 통하지 않은 경우) TypeExcludeFilter 를 등록해야 합니다. 자세한 내용은 the Javadoc을 참조하세요.

2.3.4. Using Application Arguments

application이 arguments를 예상하는 경우 args attribute를 사용하여 @SpringBootTest 에 주입하도록 할 수 있습니다.

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest(args = "--app.test=one")
class ApplicationArgumentTests {

    @Test
    void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
        assertThat(args.getOptionNames()).containsOnly("app.test");
        assertThat(args.getOptionValues("app.test")).containsOnly("one");
    }

}

2.3.5. Testing with a mock environment

default로 @SpringBootTest 는 server를 시작하지 않습니다. 만약 mock environment에 테스트하려는 web endpoint가 있는 경우 다음 예제와 같이 MockMvc 를 추가로 구성할 수 있습니다:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTests {

    @Test
    void exampleTest(@Autowired MockMvc mvc) throws Exception {
        mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
    }

}
만약 web layer에만 집중하고 전체 ApplicationContext 를 시작하지 않으려면 @WebMvcTest 를 대신 사용하는 것을 고려하세요.

또는 WebTestClient 를 다음 예제와 같이 구성할 수 있습니다.

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest
@AutoConfigureWebTestClient
class MockWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello World");
    }

}

mock environment에서 테스트 하는 것은 일반적으로 전체 Servlet container를 실행하는 것보다 빠릅니다. 그러나 mocking은 Spring MVC layer에서 발생하기 때문에 하위 수준의 Servlet container 동작에 의존하는 코드는 MockMvc로 직접 테스트 할 수 없습니다.

예를 들어 Spring Boot의 오류 처리는 Servlet container에서 제공하는 “error page” 지원을 기반으로 합니다. 이것은 MVC layer가 기대한대로 exception을 throw하고 처리하는 것을 테스트 할 수 있지만 특정 custom error page가 렌더링되었는지 직접 테스트 할 수는 없습니다. 이러한 lover-level의 문제를 테스트해야 하는 경우 다음 섹션에 섦명된 대로 완전히 실행중인 서버를 시작할 수 있습니다.

2.3.6. Testing with a running server

전체 실행 서버를 시작해야하는 경우 random port를 사용하는 것이 좋습니다. @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 를 사용하는 경우 테스트가 실행될 때마다 사용 가능한 port가 무작위로 선택됩니다.

@LocalServerPort annotation은 사용하는 실제 port 주입 테스트에 사용됩니다. 편의를 위해 시작된 서버에 대한 REST 호출을 수행해야 하는 테스트는 @Autowire 를 추가로 WebTestClient 로 할 수 있는데, 이 client는 실행 중인 서버에 대한 상대 link를 확인하고 응답을 확인하기 위한 전용 API를 제공합니다.

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RandomPortWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello World");
    }

}

이 설정은 classpath에 spring-webflux 를 필요로 합니다. webflux를 추가할 수 없거나 추가하지 않은 경우 Spring Boot는 다음과 같은 TestRestTemplate 기능도 제공합니다:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;

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

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RandomPortTestRestTemplateTests {

    @Test
    void exampleTest(@Autowired TestRestTemplate restTemplate) {
        String body = restTemplate.getForObject("/", String.class);
        assertThat(body).isEqualTo("Hello World");
    }

}

2.3.7. Customizing WebTestClient

WebTestClient bean을 customize하려면 WebTestClientBuilderCustomizer bean을 구성하면 됩니다. WebTestClient.Builder 로 호출된 bean은 WebTestClient 을 만드는데 사용됩니다.

2.3.8. Using JMX

test context framework가 context를 cache 하기 때문에 JMX는 default로 비활성화되어 동일한 구성 요소가 동일한 도메인에 등록되지 않도록 합니다. 만약 테스트가 MBeanServer 에 접근해야 하는 경우 dirty mark도 고려해야 합니다.

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

import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;

@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class SampleJmxTests {

    @Autowired
    private MBeanServer mBeanServer;

    @Test
    void exampleTest() throws MalformedObjectNameException {
        assertThat(this.mBeanServer.getDomains()).contains("java.lang");
        // ...
    }

}

2.3.9. Using Metrics

classpath와 관계없이 @SpringBootTest 를 사용할 때 지원되는 in-memory를 제외한 meter registry는 자동으로 구성되지 않습니다. 통합 테스트의 일부로 metric을 다른 backend로 내보내야 하는 경우 @AutoConfigureMetrics annotation을 추가합니다.

2.3.10. Mocking and Spying Beans

테스트를 실행할 때 때때로 application context 내에서 득정 구성 요소를 mock으로 처리해야 하는 경우가 있습니다. 예를 들면 개발 중에 사용할 수 없는 일부 원격 서비스에 대한 facade가 있을 수 있습니다. mocking은 실제 환경에서 trigger 하기 어려울 수 있는 실패를 시뮬레이션 하는 경우에도 유용할 수 있습니다.

Spring Boot는 ApplicationContext 내부 bean에 대한 Mockito mock을 정의한는데 사용하기 위한 @MockBean annotation을 포함하고 있습니다. annotation을 사용하여 새 bean을 추가하거나 기존 single bean 정의를 바꿀 수 있습니다. annotation은 test class, test class내의 field 또는 @Configuration class와 field에서 직접 사용할 수 있습니다. field에서 사용하면 생성된 mock instance도 inject 됩니다. mock bean은 각 테스트 method 실행 이후 reset 됩니다.

테스트에서 Spring Boot의 test annotation (예를 들면 @SpringBootTest) 중 하나를 사용하는 경우 이 기능은 자동으로 활성화 됩니다. 이 기능을 다른 arrangement로 사용하려면 다음 예와 같이 listener를 명시적으로 추가해야 합니다.

@TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class })

다음 예제는 기존 RemoteService bean을 mock 구현으로 대체합니다.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@SpringBootTest
class MyTests {

    @MockBean
    private RemoteService remoteService;

    @Autowired
    private Reverser reverser;

    @Test
    void exampleTest() {
        // RemoteService has been injected into the reverser bean
        given(this.remoteService.someCall()).willReturn("mock");
        String reverse = reverser.reverseSomeCall();
        assertThat(reverse).isEqualTo("kcom");
    }

}
@MockBean 은 application context가 refresh되는 동안 실행되는 bean의 동작을 mock 처리하는데 사용할 수 없습니다. test가 실행될 때 application context refresh가 완료되어 mock behavior가 구성되기에는 너무 늦습니다. 이런 경우 @Bean method를 생성하고 구성하여 mock을 만다는 것이 좋습니다.

또한 @SpyBean 을 사용하여 Mockito spy 로 기존 beand을 wrapping 할 수 있습니다. 자세한 내용은 Javadoc을 참조하세요

scoped bean 생성같은 CGLIB proxy는 proxy된 method를 final 로 선언합니다. 이는 default configuration에서 final method를 mock 처리하거나 spy 처리 할 수 없기 때문에 올바르게 작동하지 않습니다. 만약 이런 bean을 mock 또는 spy 처리하고 싶다면 org.mockito:mockito-inline 를 application의 test dependencies에 추가하여 Mockito가 inline mock maker를 사용하도록 구성합니다.
Spring의 test framework는 test 간 applciation context를 cache하고 동일한 구성을 공유하는 테스트를 위해 context를 재사용하지만 @MockBean 또는 @SpyBean 의 사용은 cache key에 영향을 미쳐 context를 늘릴 가능성이 높습니다.
만약 name으로 parameter를 참조하는 @Cacheable method가 있는 bean을 감시하기 위해 @SpyBean 을 사용하는 경우 application은 -parameters 로 compile 되어야 합니다. 이렇게 하면 bean이 감시된 후 caching infrastructure에서 parameter name을 사용할 수 있습니다.
@SpyBean 을 사용하여 Spring의 proxy 된 bean을 감시할 때 given 이나 when 을 사용하여 expectations을 설정할 때처럼 경우에 따라 Spring의 proxy를 제거해야 할 수 있습니다. 그렇게 하려면 AopTestUtils.getTargetObject(yourProxiedSpy) 를 사용하세요

2.3.11. Auto-configured Tests

Spring Boot의 auto-configuration sytstem은 application에서 동작하지만 때로는 테스트에 너무 많은 경우가 있습니다. application의 "`slice`"를 테스트 하는데 필요한 configuration 부분만 로드하면 도움이 되는 경우가 많습니다. 예를 들면, Spring MVC controller가 URL을 올바르게 mapping하는지 테스트하고 해당 테스트에 dastabase 호출을 포함하지 않거나 또는 JPA entity를 테스트 하고 싶을 때 web layer에 관심이 없는 경우가 있습니다.

spring-boot-test-autoconfigure module은 이러한 “slices” 를 자동으로 구성하는데 사용할 수 있는 여러 annotation이 포함되어 있습니다. 각각은 auto-configuration 설정을 customize하는데 사용되는 ApplicationContext 과 하나 이상의 @AutoConfigure…​ annotations을 로드하는 @…​Test annotation으로 제공되며 비슷한 방식으로 동작합니다.

각 slice는 component scan을 적절한 component로 제한하고 매우 제한된 auto-configuration class를 로드합니다. 그 중 하나를 제외해야하는 경우 대부분의 @…​Test annotations은 excludeAutoConfiguration attribute를 제공합니다. 또는 @ImportAutoConfiguration#exclude 를 사용할 수 있습니다.
하나의 테스트에서 여러 개의 @…​Test annotations 을 사용하여 여러 "`slices`"를 포함하는 것은 지원되지 않습니다. 민액 여러 "`slices`"가 필요한 경우 @…​Test annotations 중 하나를 선택하고 다른 "`slices`"의 @AutoConfigure…​ annotations 을 직접 포함해야 합니다.
standard @SpringBootTest annotation과 함께 @AutoConfigure…​ annotations을 사용할 수도 있습니다. application을 “slicing” 하는 데 관심이 없지만 auto-configured test bean 중 일부를 원하는 경우 이 조합을 사용할 수 있습니다.

2.3.12. Auto-configured JSON Tests

object JSON serialization 과 deserialization가 예상대로 동작하는지 테스트하려면 @JsonTest annotation을 사용할 수 있습니다. @JsonTest 는 다음 library 중 하나가 될 수 있는 사용가능한 JSON mapper를 auto-configure 처리합니다.

  • Jackson ObjectMapper, any @JsonComponent beans and any Jackson Modules

  • Gson

  • Jsonb

@JsonTest 에 의해 활성화된 auto-configuration 목록은 appendix 에서 찾을 수 있습니다.

auto-configuration 요소를 구성해야 하는 경우 @AutoConfigureJsonTesters annotation을 사용할 수 있습니다.

Spring Boot는 JSON이 예상한 대로 표시되는지 확인하기 위해 JSONASsert와 JsonPath library와 함께 동작하는 AssertJ-based helper가 포함되어 있습니다. JacksonTester, GsonTester, JsonbTester, 및 BasicJsonTester class는 각각 Jackson, Gson, Jsonb 및 String에 사용할 수 있습니다. @JsonTest 를 사용할 때 test class의 helper field를 @Autowired 할 수 있습니다. 다음 예제는 Jackson의 test class를 보여줍니다:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.json.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.json.*;

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

@JsonTest
class MyJsonTests {

    @Autowired
    private JacksonTester<VehicleDetails> json;

    @Test
    void testSerialize() throws Exception {
        VehicleDetails details = new VehicleDetails("Honda", "Civic");
        // Assert against a `.json` file in the same package as the test
        assertThat(this.json.write(details)).isEqualToJson("expected.json");
        // Or use JSON path based assertions
        assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
        assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make")
                .isEqualTo("Honda");
    }

    @Test
    void testDeserialize() throws Exception {
        String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
        assertThat(this.json.parse(content))
                .isEqualTo(new VehicleDetails("Ford", "Focus"));
        assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
    }

}
JSON helper class는 표준 단위 테스트에 직접 사용할 수도 있습니다. 그렇게 하려면 @JsonTest 를 사용하지 않는 경우 @Before method에 helper의 initFields method를 호출합니다.

Spring Boot의 AssertJ-based helpers를 사용하여 주어진 JSON path에서 number value를 assert하는 경우 type에 따라 isEqualTo를 사용하지 못할 수 있습니다. 대신 AssertJ의 satisfies 를 사용하여 값이 지정된 조건과 일치한다고 assert 할 수 있습니다. 예를 들어 다음 예제에서는 실제 숫자가 0.01 의 offset 내에서 0.15 에 가까운 float value로 assert 할 수 있습니다.

assertThat(json.write(message))
    .extractingJsonPathNumberValue("@.test.numberValue")
    .satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));

2.3.13. Auto-configured Spring MVC Tests

Spring MVC controller가 예상대로 동작하는지 테스트하려면 @WebMvcTest annotation을 사용할 수 있습니다. @WebMvcTest 는 Spring MVC infrastructor를 auto-configure 하고 scanned bean을 @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, HandlerInterceptor, WebMvcConfigurer, 및 HandlerMethodArgumentResolver 로 제한합니다. @WebMvcTest annotation이 사용된 경우 일반 @Component@ConfigurationProperties bean은 scan 되지 않습니다. @EnableConfigurationProperties@ConfigurationProperties bean을 포함하는데 사용할 수 있습니다.

@WebMvcTest 에서 활성화된 auto-configuration 목록 설정은 부록(appendix)에서 찾을 수 있습니다.
Jackson Module 같은 확장 component 등록이 필요한 경우 테스트에 @Import 를 사용하여 추가적인 configuration class를 import 할 수 있습니다.

종종 @WebMvcTest 는 single controller로 제한되며 @MockBean 과 함께 사용되어 필요한 collaborator에게 mock 구현을 제공합니다.

@WebMvcTest 또한 MockMvc 를 auto-configure합니다. Mock MVC는 전체 HTTP server를 시작할 필요 없이 MVC Controller를 빠르게 테스트할 수 있는 강력한 방법을 제공합니다.

(@SpringBootTest 같은) non-@WebMvcTest 에서도 MockMvc@AutoConfigureMockMvc annotation을 통해 auto-configure 할 수도 있습니다. 아래 예제는 MockMvc 를 사용합니다:
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
                .andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
    }

}
auto-configuration의 element를 구성해야 하는 경우 (예: servlet filter를 적용해야 하는 경우) @AutoConfigureMockMvc annotation에서 attribute를 사용할 수 있습니다.

HtmlUnit 또는 Selenium을 사용하는 경우 auto-configuration은 HtmlUnit WebClient bean 및/또는 Selenuum WebDriver bean도 제공합니다. 다음 예제는 HtmlUnit을 사용합니다:

import com.gargoylesoftware.htmlunit.*;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {

    @Autowired
    private WebClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
        assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
    }

}
기본적으로 Spring Boot는 WebDriver bean을 특별한 "`scope`"에 넣어 각 테스트 후 driver가 종료되고 새 instance가 inject되도록 합니다. 이 동작을 원하지 않는 경우 @Scope("singleton")WebDriver @Bean 에 추가할 수 있습니다.
Spring Boot에 의해 생성된 webDriver scope 는 동일한 이름의 사용자 정의 scope를 대체합니다. 만약 자체 webDriver scope를 정의하면 `@WebMvcTest`를 사용할 때 동작이 중지될 수 있습니다.

만약 classpath에 Spring Security가 있다면 @WebMvcTestWebSecurityConfigurer bean을 scan합니다. 이러한 테스트에 대해 security를 완전히 비활성화하는 대신 Spring Security의 test 지원을 사용할 수 있습니다. Spring Security의 MockMvc 지원에 대한 좀더 자세한 내용은 howto.html how-to section에서 찾을 수 있습니다.

때때로 Spring MVC 테스트를 작성하는 것만으로 충분하지 않습니다. Spring Boot는 실제 서버로 전체 end-to-end 테스트를 실행하는데 도움이 됩니다.

2.3.14. Auto-configured Spring WebFlux Tests

Spring WebFlux controllers가 예상대로 작동하는지 테스트하려면 @WebFluxTest annotation을 사용할 수 있습니다. @WebFluxTest 는 Spring WebFlux infrastructure를 auto-configure 하고 scanned bean을 @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, WebFilterWebFluxConfigurer 로 제한합니다. @WebFluxTest annotation이 사용된 경우 표준 @Component@ConfigurationProperties beans은 scan 되지 않습니다. @EnableConfigurationProperties@ConfigurationProperties bean을 포함하는데 사용할 수 있습니다.

@WebFluxTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.
만약 Jackson`Module` 같은 추가 component를 등록해야 하는 경우 test에서 @Import 를 사용하여 추가 configuration class를 import 할 수 있습니다.

종종 @WebFluxTest 는 single controller로 제한되며 @MockBean 과 함께 사용되어 필요한 collaborator에게 mock 구현을 제공합니다.

@WebFluxTest 는 또한 WebTestClient 를 auto-configure합니다. 이 client는 전체 HTTP server를 시작할 필요 없이 WebFlux controller를 빠르게 테스트할 수 있는 강력한 방법을 제공합니다.

(@SpringBootTest 같은) non-@WebFluxTest 에서도 WebTestClient@AutoConfigureWebTestClient annotation을 통해 auto-configure 할 수도 있습니다. 다음 예제는 @WebFluxTestWebTestClient 를 모두 사용하는 경우입니다:
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;

@WebFluxTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private WebTestClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Honda Civic");
    }

}
mock web application에서 WebTestClient 를 사용하는 것은 현재 WebFlux에서만 작동하므로 이 설정은 현재 WebFlux application에서만 지원됩니다.
@WebFluxTest 는 functional web framework를 통해 등록된 경로를 감지할 수 없습니다. context에서 RouterFunction bean을 테스트하려면 @Import 를 통해 직접 RouterFunction 을 가져오거나 @SpringBootTest 를 사용하는 것이 좋습니다.
@WebFluxTestSecurityWebFilterChain type의 @Bean 을 통해 등록된 custom security configuration을 감지할 수 없습니다. 테스트에 포함하려면 @Import 를 통해 bean을 등록하는 configuration을 import하거나 @SpringBootTest 를 사용해야 합니다.
때때로 Spring WebFlux 테스트를 작성하는 것만으로 충분하지 않습니다. Spring Boot는 실제 서버로 전체 end-to-end 테스트를 실행하는데 도움이 됩니다.

2.3.15. Auto-configured Data Cassandra Tests

Cassandra application을 테스트하는데 @DataCassandraTest 를 사용할 수 있습니다. 기본적으로 CassandraTemplate 를 구성하고 @Table classe를 scan 하고 Spring Data Cassandra repository를 구성합니다. @DataCassandraTest annotation 이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 을 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다. (Spring Boot에서 Cassandra를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-cassandra]" 를 참조하세요.)

@DataCassandraTest 로 활성화한 auto-configuration 설정 목록은 부록 (appendix) 에서 확인할 수 있습니다.

다음 예제는 Spring Boot에일 Cassandra 테스트를 사용하기 위한 일반적인 설정을 보여줍니다:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;

@DataCassandraTest
class ExampleDataCassandraTests {

    @Autowired
    private YourRepository repository;

    //
}

2.3.16. Auto-configured Data JPA Tests

@DataJpaTest annotation을 사용하여 JPA application을 테스트할 수 있습니다. 기본적으로 @Entity class를 scan 하고 Spring Data repository를 구성합니다. classpath에 embedded database가 사용 가능한 경우 하나의 database도 구성됩니다. SQL query는 기본적으로 spring.jpa.show-sql property를 true 로 설정하여 기록됩니다. annotation의 showSql() attribute를 사용하여 비활성화 할 수 있습니다.

@DataJpaTest annotation 이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties@ConfigurationProperties bean을 포함하는데 사용될 수 있습니다.

@DataJpaTest 로 활성화된 auto-configuration 구성 목록은 부록(appendix)에서 확인할 수 있습니다.

기본적으로 data JPA 테스트는 transactional이며 각 테스트가 끝날 때 roll back 됩니다. 자세한 내용은 Spring Framework 참조 문서의 관련 section울 참조하세요. 원하지 않을 경우 다음과 같이 테스트 또는 전체 class에 대해 transaction 관리를 비활성화 할 수 있습니다:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class ExampleNonTransactionalTests {

}

Data JPA 테스트는 테스트를 위해 특별히 설계된 JPA EntityManager 의 대안을 제공하는 TestEntityManager bean을 inject 할 수 있습니다. @DataJpaTest instances 외부에서 TestEntityManager 를 사용하려는 경우 @AutoConfigureTestEntityManager annotation을 사용할 수 있습니다. 필요한 경우 JdbcTemplate 도 사용할 수 있습니다. 다음 예제는 @DataJpaTest annotation을 사용하는 경우를 보여줍니다:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;

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

@DataJpaTest
class ExampleRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    void testExample() throws Exception {
        this.entityManager.persist(new User("sboot", "1234"));
        User user = this.repository.findByUsername("sboot");
        assertThat(user.getUsername()).isEqualTo("sboot");
        assertThat(user.getVin()).isEqualTo("1234");
    }

}

In-memory embedded databases는 빠르고 설치가 필요하지 않기 때문에 일반적으로 테스트에 적합합니다. 그러나 실제 데이터베이스에 대해 테스트를 실행하려는 경우 다음 예제와 같이 @AutoConfigureTestDatabase annotation을 사용할 수 있습니다:

@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
class ExampleRepositoryTests {

    // ...

}

2.3.17. Auto-configured JDBC Tests

@JdbcTest@DataJpaTest 와 비슷하지만 Spring Data JDBC를 사용하지 않고 DataSource 만 필요한 테스트에 사용됩니다. 기본적으로 in-memory embedded database와 JdbcTemplate 를 구성합니다. @JdbcTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다.

@JdbcTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

기본적으로 JDBC 테스트는 transactional이며 각 테스트가 끝날 때 roll back 됩니다. 자세한 내용은 Spring Framework 참조 문서의 관련 section을 참조하세요. 원하지 않을 경우 다음과 같이 테스트 또는 전체 class에 대해 transaction 관리를 비활성화 할 수 있습니다:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class ExampleNonTransactionalTests {

}

만약 실제 데이터베이스에 대해 테스트를 실행하려는 경우 DataJpaTest 와 동일하게 @AutoConfigureTestDatabase annotation을 사용할 수 있습니다: ("Auto-configured Data JPA Tests" 참조)

2.3.18. Auto-configured Data JDBC Tests

@DataJdbcTest@JdbcTest 와 비슷하지만 Spring Dasta JDBC repository를 사용하는 테스트용입니다. 기본적으로 in-memory embedded database와 JdbcTemplate, Spring Data JDBC repository를 구성합니다. @DataJdbcTest annotation 이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다.

@DataJdbcTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

기본적으로 Data JDBC 테스트는 transactional이며 각 테스트가 끝날 때 roll back 됩니다. 자세한 내용은 Spring Framework 참조 문서의 관련 section을 참조하세요. 원하지 않을 경우 JDBC example에서 보여진 것처럼 테스트 또는 전체 테스트 class에 대해 transaction management를 비활성화 할 수 있습니다.

실제 데이터베이스에 대해 테스트를 실행하는 것을 선호하는 경우 DataJpaTest 와 동일하게 @AutoConfigureTestDatabase annotation을 사용할 수 있습니다: ("Auto-configured Data JPA Tests" 참조)

2.3.19. Auto-configured jOOQ Tests

@JdbcTest 와 비슷한 방식으로 @JooqTest 를 jOOQ 관련 테스트에 사용할 수 있습니다. jOOQ는 database schema와 일치하는 java-based schema에 크게 의존하므로 기존 DataSource 가 사용됩니다. in-memory database로 변경하려면 @AutoConfigureTestDatabase 을 사용하여 해당 설정을 재정의할 수 있습니다. (Spring Boot와 함께 jOOQ를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-jooq]" 을 참조하세요.) @JooqTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다.

@JooqTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

@JooqTestDSLContext 을 구성합니다. 다음 예제는 @JooqTest annotation을 사용하는 경우를 보여줍니다:

import org.jooq.DSLContext;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;

@JooqTest
class ExampleJooqTests {

    @Autowired
    private DSLContext dslContext;
}

기본적으로 JOOQ 테스트는 transactional이며 각 테스트가 끝날 때 roll back 됩니다. 원하지 않을 경우 JDBC example에서 보여진 것처럼 테스트 또는 전체 테스트 class에 대해 transaction management를 비활성화 할 수 있습니다.

2.3.20. Auto-configured Data MongoDB Tests

MongoDB applications을 테스트 하는데 @DataMongoTest 를 사용할 수 있습니다. 기본적으로 (가능한 경우) in-memory embedded MongoDB을 구성하며 MongoTemplate 을 구성하고 @Document class를 scan 하며 Spring Data MongoDB repository를 구성합니다. @DataMongoTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다. (Spring Boot와 함께 MongoDB를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-mongodb]" 을 참조하세요.)

@DataMongoTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제는 @DataMongoTest annotation을 사용하는 경우를 보여줍니다:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;

@DataMongoTest
class ExampleDataMongoTests {

    @Autowired
    private MongoTemplate mongoTemplate;

    //
}

In-memory embedded MongoDB는 빠르고 개발자 설치가 필요하지 않기 때문에 일반적으로 테스트에 적합합니다. 그러나 실제 MongoDB server에 대해 테스트를 실행하려면 다음 예와 같이 embedded MongoDB auto-configuration을 제외해야 합니다:

import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;

@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
class ExampleDataMongoNonEmbeddedTests {

}

2.3.21. Auto-configured Data Neo4j Tests

Neo4j applications을 테스트하기 위해 @DataNeo4jTest 을 사용할 수 있습니다. 기본적으로 @Node class를 scan하고 Spring Data Neo4j repository를 구성합니다. @DataNeo4jTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다. (Spring Boot와 함께 Neo4J를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-neo4j]" 을 참조하세요.)

@DataNeo4jTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제는 Spring Boot에서 Neo4J를 테스트 하기 위한 일반적인 설정을 보여줍니다:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;

@DataNeo4jTest
class ExampleDataNeo4jTests {

    @Autowired
    private YourRepository repository;

    //
}

기본적으로 Data Neo4j 테스트는 transactional이며 각 테스트가 끝날 때 roll back 됩니다. 자세한 내용은 Spring Framework 참조 문서의 관련 section을 참조하세요. 원하지 않을 경우 다음과 같이 테스트 또는 전체 테스트 class에 대해 transaction management를 비활성화 할 수 있습니다:

import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class ExampleNonTransactionalTests {

}
reactive access에서 Transactional 테스트는 지원되지 않습니다. 이 경우 위에 설명한 대로 @DataNeo4jTest 테스트를 구성해야 합니다.

2.3.22. Auto-configured Data Redis Tests

Redis applications을 테스트하기 위해 @DataRedisTest 를 사용할 수 있습니다. 기본적으로 @RedisHash class를 scan하고 Spring Data Redis repository를 구성합니다. @DataRedisTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다. (Spring Boot와 함께 Redis를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-redis]" 을 참조하세요.)

@DataRedisTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제는 @DataRedisTest annotation을 사용하는 경우를 보여줍니다:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;

@DataRedisTest
class ExampleDataRedisTests {

    @Autowired
    private YourRepository repository;

    //
}

2.3.23. Auto-configured Data LDAP Tests

LDAP applications을 테스트하기 위해 @DataLdapTest 를 사용할 수 있습니다. 기본적으로 (가능한 경우) in-memory embedded LDAP을 구성하고 LdapTemplate`을 구성하고 `@Entry class를 scan하고 Spring Data LDAP repository를 구성합니다. @DataLdapTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다. (Spring Boot와 함께 LDAP를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-ldap]" 을 참조하세요.)

@DataLdapTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제는 @DataLdapTest annotation을 사용하는 경우를 보여줍니다:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;

@DataLdapTest
class ExampleDataLdapTests {

    @Autowired
    private LdapTemplate ldapTemplate;

    //
}

In-memory embedded LDAP은 빠르고 개발자 설치가 필요하지 않기 때문에 일반적으로 테스트에 적합합니다. 그러나 실제 LDAP server에 대해 테스트를 실행하려면 다음 예와 같이 embedded LDAP auto-configuration을 제외해야 합니다:

import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;

@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class ExampleDataLdapNonEmbeddedTests {

}

2.3.24. Auto-configured REST Clients

REST client를 테스트하기 위해 @RestClientTest annotation을 사용할 수 있습니다. 기본적으로 Jackson, GSON 및 Jsonb 지원을 auto-configure하고 RestTemplateBuilder 를 구성하고 MockRestServiceServer 지원을 추가합니다. @RestClientTest annotation이 사용될 때 일반 @Component@ConfigurationProperties bean은 scan되지 않습니다. @EnableConfigurationProperties 를 사용하여 @ConfigurationProperties bean을 포함할 수 있습니다.

@RestClientTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제와 같이 @RestClientTestvalue 또는 components attribute를 사용하여 테스트할 bean을 지정해야 합니다:

@RestClientTest(RemoteVehicleDetailsService.class)
class ExampleRestClientTest {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
            throws Exception {
        this.server.expect(requestTo("/greet/details"))
                .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }

}

2.3.25. Auto-configured Spring REST Docs Tests

@AutoConfigureRestDocs annotation을 사용하여 Mock MVC, REST Assured 또는 WebTestClient로 테스트에서 Spring REST Docs를 사용할 수 있습니다. Spring REST Docs애서 JUnit extension은 필요하지 않습니다.

@AutoConfigureRestDocs 는 기본 output directory(Maven을 사용하는 경우 target/generated-snippets , Gradle을 사용하는 경우 build/generated-snippets )를 재정의 하는데 사용할 수 있습니다. 또한 문서화된 URI에서 나타나는 host, scheme 및 port를 구성하는 데 사용할 수도 있습니다.

Auto-configured Spring REST Docs Tests with Mock MVC

@AutoConfigureRestDocs 는 Servlet 기반 web application을 테스트할 때 Spring REST Docs를 사용하도록 MockMvc bean을 customize합니다. 다음 예제와 같이 @Autowired 를 사용하여 inject하고 Mock MVC와 Spring REST Docs를 사용할 때 처럼 테스트에 사용할 수 있습니다:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class UserDocumentationTests {

    @Autowired
    private MockMvc mvc;

    @Test
    void listUsers() throws Exception {
        this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
                .andExpect(status().isOk())
                .andDo(document("list-users"));
    }

}

@AutoConfigureRestDocs 의 attribute에서 제공하는 것보다 Spring REST Docs 구성에 대한 더 많은 제어가 필요한 경우 다음 예와 같이 RestDocsMockMvcConfigurationCustomizer bean을 사용할 수 있습니다:

@TestConfiguration
static class CustomizationConfiguration
        implements RestDocsMockMvcConfigurationCustomizer {

    @Override
    public void customize(MockMvcRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}

parameterized output directory에 Spring REST Docs 지원을 사용하려면 RestDocumentationResultHandler bean을 생성할 수 있습니다. auto-configuration은 이 result handler로 alwaysDo 을 호출하여 각 MockMvc 호출을 자동으로 기본 snippet을 생성하게 합니다. 아래 예제는 RestDocumentationResultHandler 가 정의듸는 것을 보여줍니다:

@TestConfiguration(proxyBeanMethods = false)
static class ResultHandlerConfiguration {

    @Bean
    public RestDocumentationResultHandler restDocumentation() {
        return MockMvcRestDocumentation.document("{method-name}");
    }

}
Auto-configured Spring REST Docs Tests with WebTestClient

@AutoConfigureRestDocs 는 reactive web application을 테스트할 때 WebTestClient 와 함께 사용할 수 있습니다. 다음 예제와 같이 @Autowired 를 사용하여 inject하고 @WebFluxTest 및 Spring REST Docs를 사용할 때처럼 테스트에 사용할 수 있습니다:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;

import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;

@WebFluxTest
@AutoConfigureRestDocs
class UsersDocumentationTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void listUsers() {
        this.webTestClient
            .get().uri("/")
        .exchange()
        .expectStatus()
            .isOk()
        .expectBody()
            .consumeWith(document("list-users"));
    }

}

@AutoConfigureRestDocs 의 attribute에서 제공하는 것보다 Spring REST Docs 구성에 대한 더 많은 제어가 필요한 경우 다음 예와 같이 RestDocsWebTestClientConfigurationCustomizer bean을 사용할 수 있습니다:

import org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;

@TestConfiguration(proxyBeanMethods = false)
public class AdvancedRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {

    @Override
    public void customize(WebTestClientRestDocumentationConfigurer configurer) {
        configurer.snippets().withEncoding("UTF-8");
    }

}
Auto-configured Spring REST Docs Tests with REST Assured

@AutoConfigureRestDocs 은 Spring REST Docs를 사용하도록 사전 구성된 RequestSpecification bean을 테스트에서 사용할 수 있도록 합니다. 다음 예제와 같이 @Autowired 를 사용하여 inject하고 REST Assured 및 Spring REST Docs를 사용할 때처럼 테스트에 사용할 수 있습니다:

import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.is;
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class UserDocumentationTests {

    @Test
    void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) {
        given(documentationSpec)
            .filter(document("list-users"))
        .when()
            .port(port)
            .get("/")
        .then().assertThat()
            .statusCode(is(200));
    }

}

@AutoConfigureRestDocs 의 attribute에서 제공하는 것보다 Spring REST Docs 구성에 대한 더 많은 제어가 필요한 경우 다음 예와 같이 RestDocsRestAssuredConfigurationCustomizer bean을 사용할 수

import org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;

@TestConfiguration(proxyBeanMethods = false)
public class AdvancedRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer {

    @Override
    public void customize(RestAssuredRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}

2.3.26. Auto-configured Spring Web Services Tests

@WebServiceClientTest 를 사용하여 Spring Web Service project를 사용하여 call web service를 사용하는 application을 테스트할 수 있습니다. 기본적으로 mock WebServiceServer bean을 구성하고 WebServiceTemplateBuilder 를 자동으로 customize 합니다. (Spring Boot에서 Web Service를 사용하는 방법에 대한 자세한 내용은 선행 챕터의 "[boot-features-webservices]" 를 참조하세요.)

@WebServiceClientTest 로 활성화된 auto-configuration 목록은 부록(appendix)에서 확인할 수 있습니다.

다음 예제는 @WebServiceClientTest annotation을 사용하는 경우를 보여줍니다:

@WebServiceClientTest(ExampleWebServiceClient.class)
class WebServiceClientIntegrationTests {

    @Autowired
    private MockWebServiceServer server;

    @Autowired
    private ExampleWebServiceClient client;

    @Test
    void mockServerCall() {
        this.server.expect(payload(new StringSource("<request/>"))).andRespond(
                withPayload(new StringSource("<response><status>200</status></response>")));
        assertThat(this.client.test()).extracting(Response::getStatus).isEqualTo(200);
    }

}

2.3.27. Additional Auto-configuration and Slicing

각 slice는 slice의 일부로 포함되어야 하는 auto-configuration을 정의하는 하나 이상의 @AutoConfigure…​ annotation을 제공합니다. custom @AutoConfigure…​ annotation을 생성하거나 다음 예와 같이 @ImportAutoConfiguration 을 테스트에 추가하여 테스트 별로 추가 auto-configuration을 추가할 수 있습니다:

@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class ExampleJdbcTests {

}
auto-configuration은 Spring Boot에서 특정 방식으로 처리되므로 일반 @Import annotation을 사용하여 import 하지 마세요.

Alternatively, additional auto-configurations can be added for any use of a slice annotation by registering them in META-INF/spring.factories as shown in the following example:

org.springframework.boot.test.autoconfigure.jdbc.JdbcTest=com.example.IntegrationAutoConfiguration
@ImportAutoConfiguration 으로 meta-annotation이 있기만 하면 slice 또는 @AutoConfigure…​ annotation을 이 방법으로 customize 할 수 있습니다.

2.3.28. User Configuration and Slicing

합리적인 방식으로 code를 구조화하면 @SpringBootApplication class가 기본적으로 테스트 구성으로 사용됩니다.

그런 다음 application의 main class를 기능의 특정 영역에 특정한 구성 성질으로 흩어지지 않게 하는 것이 중요해집니다.

Spring Batch를 사용하고 있으며 auto-configuration에 의존한다고 가정해보세요. @SpringBootApplication 을 다음과 같이 정의할 수 있습니다:

@SpringBootApplication
@EnableBatchProcessing
public class SampleApplication { ... }

이 class는 테스트를 위한 source configuration이기 때문에 모든 slice 테스트는 실제로 Spring Batch를 시작하려고 시도합니다. 이는 확실히 원하는 작업이 아닙니다. 다음 예제와 같이 해당 영역별 구성을 application과 동일한 수준의 별도 @Configuration class로 이동하는 것이 좋습니다:

@Configuration(proxyBeanMethods = false)
@EnableBatchProcessing
public class BatchConfiguration { ... }
application의 복잡도에 따라 사용자 지정을 위한 단일 @Configuration class 또는 domain 영역 당 하나의 class를 가질 수 있습니다. 후자의 접근 방식을 사용하면 필요한 경우 @Import annotation을 사용하여 테스트 중 하나에서 활성화 할 수 있습니다.

테스트 slice는 scann으로 부터 @Configuration class를 제외합니다. 예를 들어 @WebMvcTest 의 경우 다음 구성은 test slice에서 로드된 application context에 지정된 WebMvcConfigurer bean을 포함하지 않습니다:

@Configuration
public class WebConfiguration {
    @Bean
    public WebMvcConfigurer testConfigurer() {
        return new WebMvcConfigurer() {
            ...
        };
    }
}

그러나 아래 구성에서는 test slice에 의해 custom WebMvcConfigurer 가 로드됩니다.

@Component
public class TestWebMvcConfigurer implements WebMvcConfigurer {
    ...
}

또 다른 혼란의 원인은 classpath scan입니다. 합리적인 방식으로 code를 구성하는 동안 추가 package를 scan해야 한다고 가정합니다. application은 다음 코드와 유사 할 수 있습니다:

@SpringBootApplication
@ComponentScan({ "com.example.app", "org.acme.another" })
public class SampleApplication { ... }

이렇게 하면 선택한 slice에 관계 없이 두 package를 scan 하는 부작용이 있는 기본 component scan directive(지시문)이 효과적으로 재정의 됩니다. 예를 들어 @DataJpaTest 는 갑자기 application의 component와 user configuration을 scan하는 것처럼 보입니다. 다시 말하면, custom directive를 별도의 class로 이동하는 것이 이 문제를 해결하는 좋은 방법입니다.

이 옵션이 선택 사항이 아닌 경우 테스트 계층 아딘가에 @SpringBootConfiguration 을 생성하여 대신 사용할 수 있습니다. 또는 테스트 source를 지정하여 default source를 찾는 동작을 비활성화 할 수 있습니다.

2.3.29. Using Spock to Test Spring Boot Applications

Spock을 사용하여 Spring Boot application을 테스트하려면 Spock의 spock-spring module에 대한 dependency를 application buill에 추가해야합니다. spock-spring 은 Spring의 test framework를 Spock에 통합합니다. 자세한 내용은 Spock의 Spring module을 위한 문서 를 참조하세요.

Spring Boot 2.5.x 및 Groovy 3.x 지원 시 spock을 사용할 수 있는 두가지 option이 있습니다: 최신 Spock 2.0 milestone 이나 Groovy 3.x와 호환되는 release를 사용하거나 Spock 1.3과 함께 사용하고 Spring Boot의 Groovy 버전을 2.5.x로 downgrade 합니다.

2.4. Test Utilities

application을 테스트 할 때 일반적으로 유용한 몇가지 test utility class가 spring-boot 의 일부로 packaging 됩니다.

2.4.1. ConfigFileApplicationContextInitializer

ConfigFileApplicationContextInitializer 은 Spring Boot application.properties file을 로드하는 테스트에 적용할 수 있는 ApplicationContextInitializer 입니다. 다음 예제와 같이 @SpringBootTest 에서 제공하는 기능의 full set이 필요하지 않을 때 사용할 수 있습니다:

@ContextConfiguration(classes = Config.class,
    initializers = ConfigFileApplicationContextInitializer.class)
ConfigFileApplicationContextInitializer 을 단독으로 사용하는 것은 @Value("${…​}") inject를 제공하지 않습니다. Spring의 Environmentapplication.properties file이 로드되도록 하는 것만이 유일한 작업입니다. @Value 지원을 받으려면 PropertySourcesPlaceholderConfigurer 를 추가로 구성하거나 @SpringBootTest 를 사용해야 auto-configure가 됩니다.

2.4.2. TestPropertyValues

TestPropertyValuesConfigurableEnvironment 또는 ConfigurableApplicationContext 에 property를 빠르게 추가할 수 있도록 합니다. 다음과 같이 key=value 문자열을 사용하여 호출할 수 있습니다:

TestPropertyValues.of("org=Spring", "name=Boot").applyTo(env);

2.4.3. OutputCapture

OutputCaptureSystem.outSystem.err output을 캡처하는데 사용할 수 있는 JUnit Extension 입니다. 사용하려면 다음 예제와 같이 @ExtendWith(OutputCaptureExtension.class) 를 추가하고 CapturedOutput 을 argument로 test class constructor나 test method에 inject합니다:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;

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

@ExtendWith(OutputCaptureExtension.class)
class OutputCaptureTests {

    @Test
    void testName(CapturedOutput output) {
        System.out.println("Hello World!");
        assertThat(output).contains("World");
    }

}

2.4.4. TestRestTemplate

TestRestTemplate 은 Spring의 RestTemplate 을 편하게 대체하여 통합 테스트에 유용합니다. vanilla template 또는 Basic HTTP authentication을 보내는 template(사용자 이름 및 암호 포함)을 얻을 수 있습니다. 두 경우 모두 template은 server-side error에 exception을 throw하지 않고 테스트하기 쉬운 방식으로 작동합니다.

Spring Framework 5.0은 WebFlux 통합 테스트WebFlux 및 MVC end-to-end 테스트에 모두 적합한 새로운 WebTestClient 를 제공합니다. TestRestTemplate 과 달리 assertion에 뛰어난 API를 제공합니다.

Apache HTTP client(version 4.3.2 이상)를 사용하는 것이 좋습니다. classpath에 해당 항목이 있는 경우 TestRestTemplate 는 client를 적절하게 구성하여 응답합니다. Apache의 HTTP client를 사용하는 경우 테스트하기 쉬운 일부 추가 기능이 사용되도록 설정됩니다:

  • redirect가 수행되지 않으므로 response location을 assert 할 수 있습니다.

  • cookie가 무시되므로 template은 stateless 입니다.

TestRestTemplate 은 다음 예제와 같이 통합 테스트에서 직접 인스턴스화 할 수 있습니다:

public class MyTest {

    private TestRestTemplate template = new TestRestTemplate();

    @Test
    public void testRequest() throws Exception {
        HttpHeaders headers = this.template.getForEntity(
                "https://myhost.example.com/example", String.class).getHeaders();
        assertThat(headers.getLocation()).hasHost("other.example.com");
    }

}

또는 @SpringBootTest annotation을 사용하는 경우 WebEnvironment.RANDOM_PORT 또는 WebEnvironment.DEFINED_PORT 로 완전히 설정된 TestRestTemplate 를 inject하고 사용할 수 있습니다. 필요한 경우 RestTemplateBuilder bean을 통해 추가 customize를 할 수 있습니다. host 및 port를 지정하지 않은 URL은 다음 예제와 같이 embedded server에 자동으로 연결됩니다:

import java.time.Duration;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;

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

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class SampleWebClientTests {

    @Autowired
    private TestRestTemplate template;

    @Test
    void testRequest() {
        HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();
        assertThat(headers.getLocation()).hasHost("other.example.com");
    }

    @TestConfiguration(proxyBeanMethods = false)
    static class RestTemplateBuilderConfiguration {

        @Bean
        RestTemplateBuilder restTemplateBuilder() {
            return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
                    .setReadTimeout(Duration.ofSeconds(1));
        }

    }

}