본문 바로가기
FrameWork/Spring

기존 테스트에 Security 적용

by 태윤2 2021. 8. 21.

test 폴더에 application.yml (테스트 용) 파일 만들기

경로

 

설정

spring-security-test 추가(build.gradle)

 

PostsApiControllerTest 에 임의 사용자 인증 추가

  • postsCreate, postsUpdate에 @WithMockUser(roles = "USER") 추가

  1. @WIthMockUser(roles = "USER")
    • 인증된 모의(가짜) 사용자를 만들어서 사용
    • roles에 권한을 추가할 수 있음
    • 이 어노테이션으로 인해 ROLE_USER 권한을 가진 사용자가 API를 요청하는 것과 동일한 효과
    • MockMvc에서만 작동함

@SpringBootTest에서 MockMvc를 사용하는 방법

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class PostsApiControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private PostsRepository postsRepository;

    @Autowired
    private WebApplicationContext context;

    @Autowired
    private MockMvc mvc;

    @BeforeEach
    public void setup() {
        MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity()) // SecurityMockMvcConfigurers.springSecurity()
                .build();
    }

    @AfterEach
    public void tearDown() throws Exception {
        postsRepository.deleteAll();
    }

    @Test
    @WithMockUser(roles = "USER")
    public void postsCreate() throws Exception {
        //given
        String title = "title";
        String content = "content";
        PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder()
                .title(title)
                .content(content)
                .author("author")
                .build();

        String url = "http://localhost:" + port + "/api/v1/posts";

        //when
        mvc.perform(
                post(url) // MockMvcRequestBuilders.post()
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(new ObjectMapper().writeValueAsString(requestDto)))
                .andExpect(status().isOk()); // (MockMvcResultMatchers.status().isOk()


//        ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url, requestDto, Long.class);

        //then


//        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
//        assertThat(responseEntity.getBody()).isGreaterThan(0L);

        List<Posts> all = postsRepository.findAll();
        assertThat(all.get(0).getTitle()).isEqualTo(title);
        assertThat(all.get(0).getContent()).isEqualTo(content);
    }

    @Test
    @WithMockUser(roles = "USER")
    public void postsModify() throws Exception {
        //given
        Posts savedPosts = postsRepository.save(Posts.builder()
                .title("title")
                .content("content")
                .author("author")
                .build());

        Long updateId = savedPosts.getId();
        String expectedTitle = "title2";
        String expectedContent = "content2";

        PostsUpdateRequestDto requestDto = PostsUpdateRequestDto.builder()
                .title(expectedTitle)
                .content(expectedContent)
                .build();

        String url = "http://localhost:" + port + "/api/v1/posts/" + updateId;

        HttpEntity<PostsUpdateRequestDto> requestEntity = new HttpEntity<>(requestDto);

        System.out.println(url);
        //when
        mvc.perform(
                put(url) // MockMvcRequestBuilders.post()
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(new ObjectMapper().writeValueAsString(requestDto))
        ).andExpect(status().isOk());

//        ResponseEntity<Long> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, requestEntity, Long.class);


        //then
//        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
//        assertThat(responseEntity.getBody()).isGreaterThan(0L);

        List<Posts> all = postsRepository.findAll();
        assertThat(all.get(0).getTitle()).isEqualTo(expectedTitle);
        assertThat(all.get(0).getContent()).isEqualTo(expectedContent);


    }
}

HelloControllerTest 문제 해결

  • WebMvcTest는 @Repository, @Service, @Compnent는 스캔 대상이 아님
  • 그러니 SecurityConfig는 읽었지만 CustomOAuth2UserService는 읽을수가 없음
  • 스캔 대상에서 SecurityConfig를 제거
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = HelloController.class,
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
        })
  • @WithMockUser를 사용해 가짜로 인증된 사용자 생성
  • 추가로 @EnableJpaAuditing을 사용하기위해선 최소 하나의 @Entity 클래스가 필요(@WebMvcTest에는 없음)\
  • @EnableJpaAuditing과 @SpringBootApplication을 분리 후 JpaConfig생성
@SpringBootApplication
//@EnableJpaAuditing // JPA Auditing 활성화
public class SpringBootWebserviceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootWebserviceApplication.class, args);
    }

}

경로

  • JpaConfig 코드
@Configuration
@EnableJpaAuditing // JPA Auditing(감시) 활성화
public class JpaConfig {
}

 

 

모든 테스트 통과

 

  • reference

스프링부트와 AWS로 혼자 구현하는 웹서비스

'FrameWork > Spring' 카테고리의 다른 글

JWT 로그인 인증방식(Spring Cloud)  (0) 2021.08.28
Spring 웹 계층의 역할  (0) 2021.08.26
네이버 로그인 추가하기  (0) 2021.08.21
Session 저장소로 데이터베이스 사용하기  (0) 2021.08.21
로그인 기능 개선  (0) 2021.08.21