테스트
GET을 제외하고 모두 엑세스 토큰을 가지고 요청 하도록 테스트 수정
리소스 서버 설정
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("event");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.and()
.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/api/**")
.anonymous()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
토큰 가져오는 함수
private String getAccessToken() throws Exception {
String username = "[email protected]";
String password = "pass";
Account cmlee = Account.builder()
.email(username)
.password(password)
.roles(new HashSet<>(Arrays.asList(AccountRole.ADMIN, AccountRole.USER)))
.build();
this.accountService.saveAccount(cmlee);
String clientId = "myApp";
String clientSecret = "secret";
ResultActions perform = this.mockMvc.perform(post("/oauth/token")
.with(httpBasic(clientId, clientSecret))
.param("username", username)
.param("password", password)
.param("grant_type", "password"));
String responseBody = perform.andReturn().getResponse().getContentAsString();
Jackson2JsonParser parser = new Jackson2JsonParser();
return parser.parseMap(responseBody).get("access_token").toString();
}
계속 동일한 id를 넣다 보니 동일한 id의 데이터가 많아져 전체 테스트가 깨진다.
@Before
public void setUp() {
this.eventRepository.deleteAll();
this.accountRepository.deleteAll();
}
public class EventControllerTest extends BaseControllerTest {
@Autowired
EventRepository eventRepository;
@Autowired
AccountService accountService;
@Autowired
AccountRepository accountRepository;
@Before
public void setUp() {
this.eventRepository.deleteAll();
this.accountRepository.deleteAll();
}
@Test
@TestDescription("정상적으로 이벤트를 생성하는 테스트")
public void createEvent() throws Exception {
EventDto event = EventDto.builder()
.name("Spring")
.description("REST API Development with Spring")
.beginEnrollmentDateTime(LocalDateTime.of(2019, 4, 17, 20, 39))
.closeEnrollmentDateTime(LocalDateTime.of(2019, 4, 18, 20, 39))
.beginEventDateTime(LocalDateTime.of(2019, 4, 20, 9, 0))
.endEventDateTime(LocalDateTime.of(2019, 4, 20, 18, 0))
.location("스타트업 팩토리")
.basePrice(100)
.maxPrice(200)
.limitOfEnrollment(100)
.build();
mockMvc.perform(post("/api/events")
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaTypes.HAL_JSON)
.content(objectMapper.writeValueAsString(event)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("id").exists())
.andExpect(header().exists(HttpHeaders.LOCATION))
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_JSON_UTF8_VALUE))
.andExpect(jsonPath("free").value(false))
.andExpect(jsonPath("offline").value(true))
.andExpect(jsonPath("eventStatus").value(EventStatus.DRAFT.name()))
.andDo(document("create-event",
links(
linkWithRel("self").description("link to self"),
linkWithRel("query-events").description("link to query events"),
linkWithRel("update-event").description("link to update an existing"),
linkWithRel("profile").description("profile")
),
requestHeaders(
headerWithName(HttpHeaders.ACCEPT).description("accept header"),
headerWithName(HttpHeaders.CONTENT_TYPE).description("content type header")
),
requestFields(
fieldWithPath("name").description("name of new event"),
fieldWithPath("description").description("description of new event"),
fieldWithPath("beginEnrollmentDateTime").description("beginEnrollmentDateTime of new event"),
fieldWithPath("closeEnrollmentDateTime").description("closeEnrollmentDateTime of new event"),
fieldWithPath("beginEventDateTime").description("beginEventDateTime of new event"),
fieldWithPath("endEventDateTime").description("endEventDateTime of new event"),
fieldWithPath("location").description("location of new event"),
fieldWithPath("basePrice").description("basePrice of new event"),
fieldWithPath("maxPrice").description("maxPrice of new event"),
fieldWithPath("limitOfEnrollment").description("limitOfEnrollment of new event")
),
responseHeaders(
headerWithName(HttpHeaders.LOCATION).description("location header for created event"),
headerWithName(HttpHeaders.CONTENT_TYPE).description("content type header")
),
relaxedResponseFields(
fieldWithPath("id").description("id of new event"),
fieldWithPath("name").description("name of new event"),
fieldWithPath("description").description("description of new event"),
fieldWithPath("beginEnrollmentDateTime").description("beginEnrollmentDateTime of new event"),
fieldWithPath("closeEnrollmentDateTime").description("closeEnrollmentDateTime of new event"),
fieldWithPath("beginEventDateTime").description("beginEventDateTime of new event"),
fieldWithPath("endEventDateTime").description("endEventDateTime of new event"),
fieldWithPath("location").description("location of new event"),
fieldWithPath("basePrice").description("basePrice of new event"),
fieldWithPath("maxPrice").description("maxPrice of new event"),
fieldWithPath("limitOfEnrollment").description("limitOfEnrollment of new event"),
fieldWithPath("free").description("it tells if this event if free"),
fieldWithPath("offline").description("it tells if this event if offline"),
fieldWithPath("eventStatus").description("event status"),
fieldWithPath("_links.self.href").description("link to self"),
fieldWithPath("_links.query-events.href").description("link to event list"),
fieldWithPath("_links.update-event.href").description("link to event update"),
fieldWithPath("_links.profile.href").description("link to profile")
)
));
}
@Test
@TestDescription("입력받을 수 없는 값을 사용한 경우에 에러가 발생하는 테스트")
public void createEvent_Bad_Request() throws Exception {
Event event = Event.builder()
.id(100)
.name("Spring")
.description("REST API Development with Spring")
.beginEnrollmentDateTime(LocalDateTime.of(2019, 4, 17, 20, 39))
.closeEnrollmentDateTime(LocalDateTime.of(2019, 4, 18, 20, 39))
.beginEventDateTime(LocalDateTime.of(2019, 4, 20, 9, 0))
.endEventDateTime(LocalDateTime.of(2019, 4, 20, 18, 0))
.basePrice(100)
.maxPrice(200)
.limitOfEnrollment(100)
.location("강남역 D2 스타트업 팩토리")
.free(true)
.offline(false)
.eventStatus(EventStatus.PUBLISHED)
.build();
mockMvc.perform(post("/api/events")
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaTypes.HAL_JSON)
.content(objectMapper.writeValueAsString(event)))
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
@TestDescription("입력 값이 비어있는 경우에 에러가 발생하는 테스트")
public void createEvent_Bad_Request_Empty_Input() throws Exception {
EventDto eventDto = EventDto.builder().build();
mockMvc.perform(post("/api/events")
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(eventDto)))
.andExpect(status().isBadRequest());
}
@Test
@TestDescription("입력 값이 잘못되어 있는 경우에 에러가 발생하는 테스트")
public void createEvent_Bad_Request_Wrong_Input() throws Exception {
EventDto eventDto = EventDto.builder()
.name("Spring")
.description("REST API Development with Spring")
.beginEnrollmentDateTime(LocalDateTime.of(2019, 4, 17, 20, 39))
.closeEnrollmentDateTime(LocalDateTime.of(2019, 4, 18, 20, 39))
.beginEventDateTime(LocalDateTime.of(2019, 4, 20, 9, 0))
.endEventDateTime(LocalDateTime.of(2019, 3, 20, 18, 0))
.basePrice(1000)
.maxPrice(200)
.limitOfEnrollment(100)
.location("강남역 D2 스타트업 팩토리")
.build();
mockMvc.perform(post("/api/events")
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(eventDto)))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("content[0].objectName").exists())
.andExpect(jsonPath("content[0].defaultMessage").exists())
.andExpect(jsonPath("content[0].code").exists())
.andExpect(jsonPath("_links.index").exists());
}
@Test
@TestDescription("30개의 이벤트를 10개씩 2번째 페이지 조회하기")
public void queryEvents() throws Exception {
// Given
IntStream.range(0, 30).forEach(this::generateEvent);
this.mockMvc.perform(get("/api/events")
.param("page", "1")
.param("size", "10")
.param("sort", "name,DESC"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("page").exists())
.andExpect(jsonPath("_embedded.eventList[0]._links.self").exists())
.andExpect(jsonPath("_links.self").exists())
.andExpect(jsonPath("_links.profile").exists())
.andDo(document("query-events"));
}
@Test
@TestDescription("기존의 이벤트를 하나 조회하기")
public void getEvent() throws Exception {
// Given
Event event = this.generateEvent(100);
this.mockMvc.perform(get("/api/events/{id}", event.getId()))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("name").exists())
.andExpect(jsonPath("id").exists())
.andExpect(jsonPath("_links.self").exists())
.andExpect(jsonPath("_links.profile").exists())
.andDo(document("get-an-event"));
}
@Test
@TestDescription("없는 이벤트 조회 했을때 404로 응답 받기")
public void getEvent404() throws Exception {
this.mockMvc.perform(get("/api/events/100"))
.andDo(print())
.andExpect(status().isNotFound());
}
@Test
@TestDescription("이벤트를 정상적으로 수정하기")
public void updateEvent() throws Exception {
Event event = this.generateEvent(200);
EventDto eventDto = this.modelMapper.map(event, EventDto.class);
String eventName = "수정한 이벤트";
eventDto.setName(eventName);
this.mockMvc.perform(put("/api/events/{id}", event.getId())
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(this.objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("name").value(eventName))
.andExpect(jsonPath("_links.self").exists())
.andDo(document("update-event"));
}
@Test
@TestDescription("입력값이 비어있는 경우의 수정 요청실패")
public void updateEvent400empty() throws Exception {
Event event = this.generateEvent(200);
EventDto eventDto = new EventDto();
this.mockMvc.perform(put("/api/events/{id}", event.getId())
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(this.objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
@TestDescription("입력값이 잘못된 경우 수정 요청실패")
public void updateEvent400wrong() throws Exception {
Event event = this.generateEvent(200);
EventDto eventDto = new EventDto();
eventDto.setBasePrice(20000);
eventDto.setMaxPrice(1000);
this.mockMvc.perform(put("/api/events/{id}", event.getId())
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(this.objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
@TestDescription("존재하지 않는 이벤트 수정 실패")
public void updateEvent404() throws Exception {
Event event = this.generateEvent(200);
EventDto eventDto = this.modelMapper.map(event, EventDto.class);
this.mockMvc.perform(put("/api/events/41223")
.header(HttpHeaders.AUTHORIZATION, getBearerToken())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(this.objectMapper.writeValueAsString(eventDto)))
.andDo(print())
.andExpect(status().isNotFound());
}
private Event generateEvent(int index) {
Event event = Event.builder()
.name("event" + index)
.description("REST API Development with Spring")
.beginEnrollmentDateTime(LocalDateTime.of(2019, 4, 17, 20, 39))
.closeEnrollmentDateTime(LocalDateTime.of(2019, 4, 18, 20, 39))
.beginEventDateTime(LocalDateTime.of(2019, 4, 20, 9, 0))
.endEventDateTime(LocalDateTime.of(2019, 4, 20, 18, 0))
.location("스타트업 팩토리")
.basePrice(100)
.maxPrice(200)
.limitOfEnrollment(100)
.free(false)
.offline(true)
.eventStatus(EventStatus.DRAFT)
.build();
return this.eventRepository.save(event);
}
private String getAccessToken() throws Exception {
String username = "[email protected]";
String password = "pass";
Account cmlee = Account.builder()
.email(username)
.password(password)
.roles(new HashSet<>(Arrays.asList(AccountRole.ADMIN, AccountRole.USER)))
.build();
this.accountService.saveAccount(cmlee);
String clientId = "myApp";
String clientSecret = "secret";
ResultActions perform = this.mockMvc.perform(post("/oauth/token")
.with(httpBasic(clientId, clientSecret))
.param("username", username)
.param("password", password)
.param("grant_type", "password"));
String responseBody = perform.andReturn().getResponse().getContentAsString();
Jackson2JsonParser parser = new Jackson2JsonParser();
return parser.parseMap(responseBody).get("access_token").toString();
}
private String getBearerToken() throws Exception {
return "Bearer " + getAccessToken();
}
}