개발강의정리/Spring

[스프링 기반 REST API 개발] 6-1. 깨진 테스트 살펴보기

nineDeveloper 2020. 4. 12.
728x90

스프링 기반 REST API 개발

6. 보강

포스팅 참조 정보

GitHub

공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다

해당 포스팅에 대한 내용의 GitHub 주소

실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다

https://github.com/freespringlecture/spring-rest-api-study/tree/chap06-01_broken_test_modify

해당 포스팅 참고 인프런 강의

https://www.inflearn.com/course/spring_rest-api/dashboard

실습 환경

  • Java Version: Java 11
  • SpringBoot Version: 2.1.2.RELEASE

1. 깨진 테스트 살펴보기

EventControllerTests.updateEvent()

깨지는 이유 및 기존 소스코드

기존 Manager가 있고 AccessToken이 들어온 경우에는 링크가 추가로 보이고 아니면 안보이게 했어야 하는데 그렇게 하지 않아서 오류가 발생
generateEventManagernull 이라서 NullPointerException이 발생하는 상태


...

private String getBearerToken() throws Exception {
    return "Bearer " + getAccessToken();
}

 /**
  * 인증 토큰을 발급
  * @return
  * @throws Exception
  */
private String getAccessToken() throws Exception {
    // Given
    Account freelife = Account.builder()
            .email(appProperties.getUserUsername())
            .password(appProperties.getUserPassword())
            .roles(Set.of(AccountRole.ADMIN, AccountRole.USER))
            .build();
    this.accountService.saveAccount(freelife);

    ...

}

...

@Test
@TestDescription("이벤트를 정상적으로 수정하기")
public void updateEvent() throws Exception {
    // Given
    Event event = this.generateEvent(200);

    ...

}

...

private Event generateEvent(int index) {
    Event event = Event.builder()
            .name("event " + index)
            .description("test event")
            .beginEnrollmentDateTime(LocalDateTime.of(2018, 11, 23, 14, 21))
            .closeEnrollmentDateTime(LocalDateTime.of(2018, 11, 24, 14, 21))
            .beginEventDateTime(LocalDateTime.of(2018, 11, 25, 14, 21))
            .endEventDateTime(LocalDateTime.of(2018, 11, 26, 14, 21))
            .basePrice(100)
            .maxPrice(200)
            .limitOfEnrollment(100)
            .location("강남역 D2 스타텁 팩토리")
            .free(false)
            .offline(true)
            .eventStatus(EventStatus.DRAFT)
            .build();

    return this.eventRepository.save(event);
}

해결방법

updateEvent() 수행시 Account를 신규로 생성해서 Event 생성 메서드에 account 파라메터를 넘겨
Manager를 셋팅해서 저장하도록 수정

  • getAcessToken에 포함되어있던 Account 생성 기능을 createAccount()로 리팩토링
  • getBearerToken을 오버로딩하여 boolean needToCreateAccount을 파라메터로 받는 메서드와 파라메터를 받지 않으면
    true를 기본값으로 대입하도록 수정
  • getAccessToken 메서드는 needToCreateAccount 파라메터에 따라 createAccount()를 수행하여 회원정보를 생성하도록 수정
  • updeateEvent 메서드를 createAccount()를 수행하여 생성한 accountgenerateEvent에 추가로 파라메터 전달
  • generateEvent 메서드가 account 파라메터를 추가로 받으면 Manager에 파라메터로 받은 account를 셋팅해서 저장
    index 파라메터만 받는다면 기존과 동일하게 event 객체를 저장
  • generateEvent에 포함되어있던 Event BuilderbuildEvent로 리팩토링
// 오버로딩하여 파라메터를 받지 않으면 getAccessToken에 true를 기본 파라메터로 전달
private String getBearerToken() throws Exception {
    return getBearerToken(true);
}

// needToCreateAccount 파라메터를 받아서 getAccessToken에 파라메터를 전달
private String getBearerToken(boolean needToCreateAccount) throws Exception {
    return "Bearer " + getAccessToken(needToCreateAccount);
}

 /**
  * 인증 토큰을 발급
  needToCreateAccount 파라메터에 따라 createAccount()를 수행하여 회원정보를 생성하도록 수정
  * @return
  * @throws Exception
  */
private String getAccessToken(boolean needToCreateAccount) throws Exception {
    // Given
    if(needToCreateAccount)
        createAccount();

    ...

}

// getAcessToken에 포함되어있던 Account 생성 기능을 createAccount()로 리팩토링
private Account createAccount() {
    Account freelife = Account.builder()
            .email(appProperties.getUserUsername())
            .password(appProperties.getUserPassword())
            .roles(Set.of(AccountRole.ADMIN, AccountRole.USER))
            .build();
    return this.accountService.saveAccount(freelife);
}

// Account를 createAccount()를 수행하여 생성하고 generateEvent에 account 파라메터를 추가로 전달
@Test
@TestDescription("이벤트를 정상적으로 수정하기")
public void updateEvent() throws Exception {
    // Given
    Account account = this.createAccount();
    Event event = this.generateEvent(200, account);

    ...

}

// account 파라메터를 추가로 받으면 Manager에 파라메터로 받은 account를 셋팅해서 저장
private Event generateEvent(int index, Account account) {
    Event event = buildEvent(index);
    event.setManager(account);
    return this.eventRepository.save(event);
}

// index만 있으면 기존과 동일하게 event 객체를 저장
private Event generateEvent(int index) {
    Event event = buildEvent(index);
    return this.eventRepository.save(event);
}

// generateEvent에 포함되어있던 Event Builder 를 buildEvent로 리팩토링
private Event buildEvent(int index) {
    return Event.builder()
                .name("event " + index)
                .description("test event")
                .beginEnrollmentDateTime(LocalDateTime.of(2018, 11, 23, 14, 21))
                .closeEnrollmentDateTime(LocalDateTime.of(2018, 11, 24, 14, 21))
                .beginEventDateTime(LocalDateTime.of(2018, 11, 25, 14, 21))
                .endEventDateTime(LocalDateTime.of(2018, 11, 26, 14, 21))
                .basePrice(100)
                .maxPrice(200)
                .limitOfEnrollment(100)
                .location("강남역 D2 스타텁 팩토리")
                .free(false)
                .offline(true)
                .eventStatus(EventStatus.DRAFT)
                .build();
}

EventControllerTests.getEvent()

깨지는이유 및 소스코드

마찬가지로 getEvent() 테스트 코드도 generateEventManagernull 이라서 NullPointerException이 발생하는 상태

@Test
@TestDescription("기존의 이벤트를 하나 조회하기")
public void getEvent() throws Exception {
    // Given
    Event event = this.generateEvent(100);

    ...

}

해결방법 및 소스코드

createAccount()를 수행하여 생성한 accountgenerateEvent에 추가로 파라메터 전달

// Account를 createAccount()를 수행하여 생성하고 generateEvent에 account 파라메터를 추가로 전달
@Test
@TestDescription("기존의 이벤트를 하나 조회하기")
public void getEvent() throws Exception {
    // Given
    Account account = this.createAccount();
    Event event = this.generateEvent(100, account);

    ...

}

DemoApplicationTests

깨지는이유 및 소스코드

이 테스트 코드는 application-test.properties 파일에서 설정을 읽어오지 않고 application.properties 파일에서 설정을 읽어오기 떄문에 h2 DB를 사용하지 않고 현재 띄워놓지 않은 PostgreSQL 커넥션을 시도하면서 테스트가 실패함

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    @Test
    public void contextLoads() {
    }

}

해결방법 및 소스코드

@ActiveProfiles("test") 어노테이션을 추가해서 application-test.properties 파일에서 설정을 읽어 오도록 수정하면 테스트가 성공한다

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class ApplicationTests {

    @Test
    public void contextLoads() {
    }

}

BaseControllerTest -> BaseTest 로 클래스명 정정

public class BaseTest {
728x90

댓글

💲 추천 글