Programming/Spring

[스프링부트 (9)] SpringBoot Test(2) - @SpringBootTest로 통합테스트 하기

byeong07 2022. 5. 29. 22:47

[스프링부트 (9)] SpringBoot Test(2) - @SpringBootTest로 통합테스트 하기

이번 포스팅은 [ 스프링 부트  통합 테스트 하기 (@SpringBootTest)입니다. : ) 

 

 

 

 

0. 들어가기 앞서

이번 포스팅의 대부분의 내용은 공식 레퍼런스 문서에 더 자세하게 나와 있다.

다음 공식 문서를 꼭 참고 하면 좋을 것 같다.
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing

 

SpringBoot는 테스트 목적에 따라 다양한 어노테이션을 제공한다. 

 

☞  통합테스트

@SpringBootTest

 

단위테스트

@WebMvcTest, @DataJpaTest, @RestClientTest, @JsonTest 등등

 

이 중 오늘은 @SpringBootTest를 사용하여 아주 간단한 통합 테스트를 해보려 한다.

이를 위해 Spring Boot에서는 "spring-boot-starter-test"를 제공한다.
이전 포스팅에 이미 작성해 두었지만, "spring-boot-starter-test" 에는 다음 라이브러리들이 포함되어 있다.
 
 - JUnit 5 (including the vintage engine for backward compatibility with JUnit 4): The de-facto standard for unit testing Java applications.
 - Spring Test & Spring Boot Test: Utilities and integration test support for Spring Boot applications.
 - AssertJ: A fluent assertion library.
 - Hamcrest: A library of matcher objects (also known as constraints or predicates).
 - Mockito: A Java mocking framework.
 - JSONassert: An assertion library for JSON.
 - JsonPath: XPath for JSON.

 

스프링 이니셜라이져로 프로젝트를 생성한 경우 이미 "spring-boot-starter-test"가 디펜던시 추가되어 있을 것이다.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.junit.vintage</groupId>
      <artifactId>junit-vintage-engine</artifactId>
  	</exclusion>
  </exclusions>
</dependency>

해당 디펜던시 하나면 테스트 준비는 완료 된 상태이다.

 

1. 통합 테스트

▶ 1. 통합 테스트

1) 개요
 - 실제 운영 환경에서 사용될 클래스들을 통합하여 테스트 한다.
 - 단위 테스트와 같이 기능 검증을 위한 것이 아니라 spring framework에서 전체적으로 플로우가 제대로 동작하는지 검증하기 위해 사용 한다.
 
2) 장점
 - 애플리케이션의 설정, 모든 Bean을 모두 로드하기 때문에 운영환경과 가장 유사한 테스트가 가능하다.
 - 전체적인 Flow를 쉽게 테스트 가능하다.

3) 단점
 - 애플리케이션의 설정, 모든 Bean을 모두 로드하기 때문에 시간이 오래걸리고 무겁다.
 - 테스트 단위가 크기 때문에 디버깅이 어려운 편이다.

▶ @SpringBootTest

 - 스프링 부트는 @SpringBootTest 어노테이션을 통해 스프링부트 어플리케이션 테스트에 필요한 거의 모든 의존성을 제공한다.

 - @SpringBootTest는 통합 테스트를 제공하는 기본적인 스프링 부트 테스트 어노테이션 이다.

 - 해당 어노테이션을 사용시 Junit 버전에 따라 유의할 사항이 있다. (공식문서 참고)

 

If you are using JUnit 4, don’t forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be ignored.
Junit4 사용시 @SpringBootTest 기능은 반드시 JUnit의 SpringJUnit4ClassRunner 클래스를 상속 받는 @RunWith(SpringRynnver.class)와 함께 사용해야 한다.
 
If you are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest 
and the other @…Test annotations are already annotated with it.
 Junit5 사용시에는 해당 어노테이션은 명시할 필요없다.

 

① properties

1.1) 프로퍼티를 {key=value} 형식으로 직접 추가할 수 있다.

//@RunWith(SpringRunner.class) => Junit4 사용시 추가, Junit5 사용시 생략.
@SpringBootTest(
	properties = {
		"propertyTest.value=propertyTest",
		"testValue=test"
	}
)
// ... 중략
@Value("${propertyTest.value}")
private String propertyTestValue; //propertyTest

@Value("${testValue}")
private String value; //test

1.2)  기본적으로 클래스 경로상의 application.properties(또는 application.yml)를 통해 애플리케이션 설정을 수행 한다.
 하지만 테스트를 위한 다른 설정이 필요하다면 다른 프로퍼티를 로드할 수 있다.

//@RunWith(SpringRunner.class) => Junit4 사용시 추가, Junit5 사용시 생략.
@SpringBootTest(
	properties = {"spring.config.location=classpath:application-test.properties"}
)

 

③ webEnvironment 

 - 웹 테스트 환경 구성이 가능하다.
 - webEnvironment 파라미터를 이용하여 손쉽게 웹 테스트 환경을 선택할 수 있다.

 

3.1) Mock
 - 실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려울 경우, 가짜 객체를 만들어 사용한다.
 - WebApplicationContext를 로드하며 내장된 서블릿 컨테이너가 아닌 Mock 서블릿을 제공한다.
 - 별도로 지정하지 않으면 기본값은 Mock 서블릿을 로드하여 구동하게 된다.
 - @AutoConfigureMockMvc 어노테이션을 함께 사용하면 별다른 설정 없이 간편하게 MockMvc를 사용한 테스트를 진행할 수 있다.
   MockMvc는 브라우저에서 요청과 응답을 의미하는 객체로서 Controller 테스테 사용을 용이하게 해주는 라이브러리이다.

※ @AutoConfigureMockMvc
 - Mock 테스트시 필요한 의존성을 제공해준다.
 - MockMvc 객체를 통해 실제 컨테이너가 실행되는 것은 아니지만 로직상으로 테스트를 진행할 수 있습니다. (DispatcherServlet을 로딩학여 Mockup으로 처리 가능)
 - print() 함수를 통해 좀 더 디테일한 테스트 결과를 볼 수 있다.

@Autowired 
MockMvc mvc;


3.2) RANDOM_PORT
 - EmbeddedWebApplicationContext를 로드하며 실제 서블릿 환경을 구성 한다.

 - 임의의 port listen


3.3) DEFINED_PORT
 - RAMDOM_PORT와 동일하게 실제 서블릿 환경을 구성하지만, 포트는 애플리케이션 프로퍼티에서 지정한 포트를 listen 한다.


3.4) NONE
 - 기본적인 ApplicationContext를 로드한다.


3.5) TestRestTemplate
 - webEnvironment설정시(NONE을 설정시 사용 불가) 그에 맞춰서 자동으로 설정되어 빈이 생성되며, RestTemplate의 테스트를 처리가 가능하다.

- Spring 4.x 이후부터 지원하는 Spring의 HTTP 통신 템플릿
- HTTP 요청 후 Json, xml, String 과 같은 응답을 받을 수 있는 템플릿
- Http request를 지원하는 HttpClient를 사용함
- ResponseEntity와 Server to Server 통신하는데 자주 쓰인다.
  (ResponseEntity는 응답 처리시 값 뿐만 아니라 상태코드, 응답메세지 등을 포함하여 리턴 가능하다. HttpEntity를 상속받기 떄문에 HttpHeader와 body를 가질수 있다.)
- Header, Content-Type등을 설정하여 외부 API 호출

@Autowired 
private TestRestTemplate restTemplate;

 

▶ @MockBean

 - Mock 객체를 빈으로써 등록할 수 있다.
 - @MockBean은 Spring의 ApplicationContext는 Mock 객체를 빈으로 등록하며, 혹시 @MockBean으로 선언된 객체와 같은 이름과 타입으로 이미 빈이 등록되어있다면 해당빈은 선언한 @MockBean으로 대체된다.

@MockBean
private MemberMapper memberMapper;

▶ @Transactional

 - 테스트 완료 후 자동으로 rollback 처리 한다.
   (spring-boot-test는 단순히 spring-test를 확장한 것이기 때문에 @Test 어노테이션과 함께 @Transactional 어노테이션을 함께 사용하면 테스트가 끝날 때 rollback 처리)
 - 하지만 WebEnvironment.RANDOM_PORT, DEFINED_PORT를 사용하면 실제 테스트 서버는 별도의 스레드에서 테스트를 수행하기 떄문에 트랜잭션이 롤백되지 않는다.

▶ @ActiveProfiles

 - 프로파일 전략을 사용 중이라면 원하는 프로파일 환경값 설정이 가능 하다.

 

 

▶ 실습 (test)

이제부터 예제를 통해 실행 해보고 해당 위의 내용들을 확인해 보자.

스프링부트 버전 : (SpringBoot 2.2.2 V)

 

이전 포스팅에서 JPA를 통해 CRUD를 했었는데, 해당 소스를 기반으로 테스트 하였다.

https://goddaehee.tistory.com/209

 

테스트 하였던 전체 소스는 다음과 같다. 이 전체 소스를 하나 하나 분리해서 간단히 설명 해보려 한다.

package com.god.bo.jpaTest.controller;

import com.god.bo.jpaTest.service.MemberService;
import com.god.bo.jpaTest.vo.MemberVo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.transaction.Transactional;
import java.util.Optional;

import static org.assertj.core.api.BDDAssertions.then;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.iterableWithSize;
import static org.hamcrest.core.Is.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest(
        properties = {
                "testId=goddaehee2",
                "testName=갓대희"
        }
        //classes = {TestJpaRestController.class, MemberService.class},
        ,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@Transactional
@AutoConfigureMockMvc
@Slf4j
public class TestJpaRestControllerTest {

    @Value("${testId}")
    private String testId;

    @Value("${testName}")
    private String testName;
    
    /*@MockBean
    private MemberRepository memberRepository;*/

    @Autowired
    MockMvc mvc;

    @Autowired
    private TestRestTemplate restTemplate;

    // Service로 등록하는 빈
    @Autowired
    private MemberService memberService;

    @Autowired
    private WebApplicationContext ctx;

    @BeforeEach() //Junit4의 @Before
    public void setup() {
        this.mvc = MockMvcBuilders.webAppContextSetup(ctx)
                .addFilters(new CharacterEncodingFilter("UTF-8", true))  // 필터 추가
                .alwaysDo(print())
                .build();
    }

    @Test
    void getMember() throws Exception {
        log.info("##### Properties 테스트 #####");

        /******** START : MOC MVC test **********/
        log.info("******** START : MOC MVC test **********");
        mvc.perform(get("/memberTest/1"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.id", is("goddaehee")))
                .andDo(print());
        log.info("******** END : MOC MVC test **********");
        /******** END : MOC MVC test **********/

        /******** START : TestRestTemplate test **********/
        log.info("******** START : TestRestTemplate test **********");
        ResponseEntity<MemberVo> response = restTemplate.getForEntity("/memberTest/1", MemberVo.class);
        then(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        then(response.getBody()).isNotNull();
        log.info("******** END : TestRestTemplate test **********");
        /******** END : TestRestTemplate test **********/

        /******** START : MockBean test **********/
        log.info("******** START : MockBean test **********");
        /*
        MemberVo memberVo = MemberVo.builder()
                .id(testId)
                .name(testName)
                .build();

        given(memberRepository.findById(1L))
                .willReturn(Optional.of(memberVo));*/

        Optional<MemberVo> member = memberService.findById(1L);
        if (member.isPresent()) {
            // ※ Junit4 사용시
            // assertThat(memberVo.getId()).isEqualTo(member.get().getId());
            // assertThat(memberVo.getName()).isEqualTo(member.get().getName());

            // Junit5 BDD 사용시
            then("goddaehee").isEqualTo(member.get().getId());
            then("갓대희").isEqualTo(member.get().getName());
        }
        log.info("******** END : MockBean test **********");
        /******** END : MockBean test **********/
    }
}

 

0) TestClass 생성

통합 테스트할 클래스에서 Alt + Enter 클릭 > 원하는 메소드 체크 > 확인 (Junit5로 테스트 예정)

 

 

mbrNo로 회원을 조회하는 getMember 메서드를 선택 하였다.

 

1) properties

직접 선언한 properties의 값들이 올바르게 호출되는지 확인해 보았다.

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest(
        properties = {
                "testId=goddaehee",
                "testName=갓대희"
        }
)
@Transactional
@Slf4j
public class TestJpaRestControllerTest {

    @Value("${testId}")
    private String testId;

    @Value("${testName}")
    private String testName;

    @Test
    void getMember() throws Exception {
        log.info("##### Properties 테스트 #####");
        log.info("testId : " + testId);
        log.info("testName : " + testName);
    }
}
INFO  20-02-28 00:06:46[main] [TestJpaRestControllerTest:81] - ##### Properties 테스트 #####
INFO  20-02-28 00:06:46[main] [TestJpaRestControllerTest:82] - testId : goddaehee
INFO  20-02-28 00:06:46[main] [TestJpaRestControllerTest:83] - testName : 갓대희

 

2) moc mvc

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest(
        properties = {
                "testId=goddaehee",
                "testName=갓대희"
        }
)
@Transactional
@AutoConfigureMockMvc
@Slf4j
public class TestJpaRestControllerTest {

    @Value("${testId}")
    private String testId;

    @Value("${testName}")
    private String testName;
    
    @Autowired
    MockMvc mvc;
    
    // Service로 등록하는 빈
    @Autowired
    private MemberService memberService;

    @Test
    void getMember() throws Exception {
        log.info("##### Properties 테스트 #####");
        log.info("testId : " + testId);
        log.info("testName : " + testName);
        
        /******** START : MOC MVC test **********/
        log.info("******** START : MOC MVC test **********");
        mvc.perform(get("/memberTest/1"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.id", is("goddaehee")))
                .andDo(print());
        log.info("******** END : MOC MVC test **********");
        /******** END : MOC MVC test **********/
    }
}
INFO  20-02-28 00:16:14[main] [TestJpaRestControllerTest:74] - ******** START : MOC MVC test **********
MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /memberTest/1
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {}

Handler:
             Type = com.god.bo.jpaTest.controller.TestJpaRestController
           Method = com.god.bo.jpaTest.controller.TestJpaRestController#getMember(Long)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = {"mbrNo":1,"id":"goddaehee","name":"갓대희"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
INFO  20-02-28 00:16:14[main] [TestJpaRestControllerTest:80] - ******** END : MOC MVC test **********

소스에 작성한대로 Status : 200, application/json 형태로 리턴되어 테스트에는 통과 하였다. 다만 한글이 깨져있는 것을 볼 수 있다.

 

mokMvc 한글 깨짐 현상은 MockMvc를 설정할 때 CharacterEncodingFilter를 추가 하면 해결 할 수 있다. 다음을 추가해주자.

@Autowired
private WebApplicationContext ctx;

@BeforeEach() //Junit4의 @Before
public void setup() {
this.mvc = MockMvcBuilders.webAppContextSetup(ctx)
.addFilters(new CharacterEncodingFilter("UTF-8", true))  // 필터 추가
.alwaysDo(print())
.build();
}

 

그럼 UTF-8로 세팅되어 한글 출력도 올바르게 나온다.

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json;charset=UTF-8"]
     Content type = application/json
             Body = {"mbrNo":1,"id":"goddaehee","name":"갓대희"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

 

3) TestRestTemplate

 - TestRestTemplate을 사용하기 위해선 webEnvironment을 설정 해주어야 한다.

 

ex) webEnvironment 추가 전

@Autowired
    private TestRestTemplate restTemplate;
org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'com.god.bo.jpaTest.controller.TestJpaRestControllerTest': 
Unsatisfied dependency expressed through field 'restTemplate'; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'org.springframework.boot.test.web.client.TestRestTemplate' 
available: expected at least 1 bean which qualifies as autowire candidate. 
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

 

ex) webEnvironment 추가 (RANDOM_PORT 추가)후 오류 발생하지 않음을 확인할 수 있다.

@SpringBootTest(
        properties = {
                "testId=goddaehee",
                "testName=갓대희"
        }
        ,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)

 

ex) TestRestTemplate 테스트 추가 하여 실행

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest(
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@Transactional
@AutoConfigureMockMvc
@Slf4j
public class TestJpaRestControllerTest {
    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void getMember() throws Exception {
        /******** START : TestRestTemplate test **********/
        log.info("******** START : TestRestTemplate test **********");
        ResponseEntity<MemberVo> response = restTemplate.getForEntity("/memberTest/1", MemberVo.class);
        then(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        then(response.getBody()).isNotNull();
        log.info("******** END : TestRestTemplate test **********");
        /******** END : TestRestTemplate test **********/
 	}
}

테스트가 정상적으로 종료됨을 확인할 수 있다.

 

4) @MockBean

 - MockBean으로 테스트 하기전에 기본적인 Junit Test를 먼저 예시로 들어 보려 한다.

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest
@Transactional
@AutoConfigureMockMvc
@Slf4j
public class TestJpaRestControllerTest {
	// Service로 등록하는 빈
    @Autowired
    private MemberService memberService;

    @Test
    void getMember() throws Exception {
        /******** START : TestRestTemplate test **********/
        log.info("******** START : TestRestTemplate test **********");
        ResponseEntity<MemberVo> response = restTemplate.getForEntity("/memberTest/1", MemberVo.class);
        then(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        then(response.getBody()).isNotNull();
        log.info("******** END : TestRestTemplate test **********");
        /******** END : TestRestTemplate test **********/
 	}
}
Hibernate: 
    select
        membervo0_.mbr_no as mbr_no1_0_0_,
        membervo0_.id as id2_0_0_,
        membervo0_.name as name3_0_0_ 
    from
        member membervo0_ 
    where
        membervo0_.mbr_no=?
DEBUG 20-02-28 02:00:58[main] [sqltiming:368] -  com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
1. select membervo0_.mbr_no as mbr_no1_0_0_, membervo0_.id as id2_0_0_, membervo0_.name as name3_0_0_ from member membervo0_ where membervo0_.mbr_no=1
 {executed in 7 msec}

 

 

올바르게 테스트 통과(Test passed) 하였고, 나와 같은 경우는 Database 세팅도 다 완료 하였기 떄문에 DB로그도 올바르게 찍히는것을 볼 수 있다.

하지만 실제 테스트 환경에서 시간도 없고, 특정 상황을 가정하고자 한다면 @MockBean을 통해 목객체로 선언하여 테스팅도 가능하다.

그리고 또한 다음 포스팅에서 다룰 단위 테스트 진행시, 예를들어 @WebMvcTest같은 경우 통합테스트보다 매우 가볍게 테스팅이 가능하고, DB연결 테스트를 하는게 아니기 떄문에 사용하면 유용하다. 미리 예를들어 사용 방법을 알아보자.

 

상기 소스중 Optional member = memberService.findById(1L);

memberService.findById의 결과는 다음과 같다.

{"mbrNo":1,"id":"goddaehee","name":"갓대희"}

 

이때의 결과를 id:goddaehee2 로 변경하여 테스트 해보는 예제이다

ex)

//@RunWith(SpringRunner.class) // ※ Junit4 사용시
@SpringBootTest
@Transactional
@AutoConfigureMockMvc
@Slf4j
public class TestJpaRestControllerTest {
    @MockBean
    private MemberRepository memberRepository;
	// Service로 등록하는 빈
    @Autowired
    private MemberService memberService;

    @Test
    void getMember() throws Exception {
        /******** START : MockBean test **********/
        log.info("******** START : MockBean test **********");
        MemberVo memberVo = MemberVo.builder()
                .id("goddaehee2")
                .name("갓대희")
                .build();

        given(memberRepository.findById(1L))
                .willReturn(Optional.of(memberVo));

		Optional<MemberVo> member = memberService.findById(1L);
        if (member.isPresent()) {
            // ※ Junit4 사용시
            // assertThat(memberVo.getId()).isEqualTo(member.get().getId());
            // assertThat(memberVo.getName()).isEqualTo(member.get().getName());

            // Junit5 BDD 사용시
            then("goddaehee").isEqualTo(member.get().getId());
            then("갓대희").isEqualTo(member.get().getName());
        }
        log.info("******** END : MockBean test **********");
        /******** END : MockBean test **********/
 	}
}
Expecting:
 <"goddaehee">
to be equal to:
 <"goddaehee2">
but was not., mergedContextConfiguration = [WebMergedContextConfiguration@18271936 testClass = TestJpaRestControllerTest, locations = '{}', classes = '{class com.god.bo.BoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{testId=goddaehee2, testName=갓대희, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[[ImportsContextCustomizer@606e4010 key = [org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@4466af20, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3e58a80e, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@8687fa71, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@74fe5c40, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@4b3fa0b3, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@747ddf94], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]]

에러가 발생 하였다.

실제 DB에는 "goddaehee2"가 들어가 있지만 @MockBean을 통해 가짜객체를 만들어 DB쿼리를 호출하지 않고 예상하는 값으로 설정하여 좀더 간단하게 다양한 경우를 가정하여 테스트 가능하다. 

 

다음 포스팅에선 단위 테스트 기능들도 알아보도록 하자.