[Spring REST API #8] REST API 비즈니스 로직 적용 및 JunitParam을 이용한 테스트

| Spring REST API 비즈니스 로직 적용 및 JUnitParam을 이용한 테스트

  • JUnitParam 테스트 라이브러리는 JUnit의 각 Test 메서드에 파라미터를 쓸 수 있게 함으로써 테스트 코드량을 줄이고 유지보수를 쉽게 해주는 유용한 라이브러리 이다.

테스트 할 전제조건

  • 1. basePrice와 maxPrice 가 모두 0이면 free=true 그 이외에는 free=false
  • 2. location 이 null 이거나 문자열의 길이가 0일 때 offline = false 그 외에는 offline = true

참고 URL : https://github.com/Pragmatists/JUnitParams

 

Pragmatists/JUnitParams

Parameterised tests that don't suck. Contribute to Pragmatists/JUnitParams development by creating an account on GitHub.

github.com

의존성 추가

<dependency>
  <groupId>pl.pragmatists</groupId>
  <artifactId>JUnitParams</artifactId>
  <version>1.1.1</version>
  <scope>test</scope>
</dependency>

테스트코드

package org.kyhslam.rest;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JUnitParamsRunner.class)
public class EventTest {


	@Test
    @Parameters(method = "paramsForTestFree")
    public void testFree(int basePrice, int maxPrice, boolean isFree){

        Event event = Event.builder()
                .basePrice(basePrice)
                .maxPrice(maxPrice)
                .build();

        // When
        event.update();

        // Then
        Assertions.assertThat(event.isFree()).isEqualTo(isFree);
    }

    private Object[] paramsForTestFree(){
        return new Object[] {
                new Object[] {0,0,true},
                new Object[] {0,0,true},
                new Object[] {0,0,true}
        };
    }

    @Test
    @Parameters(method = "paramsForTestOffline")
    public void testOffline(String location, boolean isOffline){
        // Given
        Event event = Event.builder()
                .location(location.trim())
                .build();

        // When
        event.update();

        // Then
        Assertions.assertThat(event.isOffline()).isEqualTo(isOffline);
    }

    private Object[] paramsForTestOffline(){
        return new Object[] {
                new Object[] {"강남",true},
                new Object[] {null,false},
                new Object[] {"  ",false}
        };
    }

}

 

  • JUnitParams를 적용하여 테스트 코드를 작성한 것을 볼 수 있습니다. @Parameters 어노테이션을 각 테스트에 명시하면 파리미터화 된 입력값을 쓸 수 있습니다.
  • 파라미터화된 입력값은 위 코드와 같이 코드 상에 명시해야 하며 parametersFor + [테스트명] 으로 작성하면 자동적으로 [테스트명]으로 작성된 테스트 메서드에 해당 입력값이 매칭되게 됩니다. 또한 @Parameters(method="[테스트명]") 형태로 직정 지정해서 쓸 수 있습니다.


소스

package org.kyhslam.rest;

import lombok.*;

import javax.persistence.*;
import java.time.LocalDateTime;

@Builder @AllArgsConstructor @NoArgsConstructor
@Setter @Getter @EqualsAndHashCode(of = "id")
@Entity
public class Event {

    @Id @GeneratedValue
    private Integer id;
    private String name;
    private String description;
    private LocalDateTime beginEnrollmentDateTime;
    private LocalDateTime closeEnrollmentDateTime;
    private LocalDateTime beginEventDateTime;
    private LocalDateTime endEventDateTime;
    private String location; // (optional)
    private int basePrice; // (optional)
    private int maxPrice; // (optional)
    private int limitOfEnrollment;
    private boolean offline;
    private boolean free;
    @Enumerated(EnumType.STRING)
    private EventStatus eventStatus = EventStatus.DRAFT;


    public void update(){
        if(this.basePrice == 0 && this.maxPrice == 0){
            this.free = true;
        }else{
            this.free = false;
        }

        // OffLine
        if(this.location == null || "".equals(this.location)){
            this.offline = false;
        }else{
            this.offline = true;
        }

    }

}

 

비즈니스 로직을 적용한 엔티티 클래스입니다. 

package org.kyhslam.rest;

import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.net.URI;

@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_UTF8_VALUE)
public class EventController {

    @Autowired
    EventRepository eventRepository;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    EventValidator eventValidator;

    public EventController(EventRepository eventRepository, ModelMapper modelMapper, EventValidator eventValidator){
        this.eventRepository = eventRepository;
        this.modelMapper = modelMapper;
        this.eventValidator = eventValidator;
    }


    @PostMapping
    public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors){
        if(errors.hasErrors()){
            return ResponseEntity.badRequest().body(errors);
        }

        eventValidator.validate(eventDto, errors);
        if(errors.hasErrors()){
            return ResponseEntity.badRequest().body(errors);
        }

        Event event = modelMapper.map(eventDto, Event.class); // Dto를 event로 변환

        event.update();

        Event newEvent = eventRepository.save(event);
        URI createdUri = ControllerLinkBuilder.linkTo(EventController.class).slash(newEvent.getId()).toUri();
        return ResponseEntity.created(createdUri).body(event);
    }

}

HTTP 요청 안에 포함된 데이터들을 Event 객체로 역직렬화한 다음 Event 객체의 update 메서드를 이용해 비즈니스 로직을 적용한 모습입니다

결과

각 Parameter에 따른 테스크 케이스 결과를 볼 수 있다.

댓글

Designed by JB FACTORY