zoaseo
To Infinity And Beyond
zoaseo
전체 방문자
오늘
어제
  • 분류 전체보기 (760)
    • 개발이 좋아서 (378)
      • Java가 좋아서 (42)
      • Spring이 좋아서 (50)
      • JPA가 좋아서 (0)
      • QueryDSL이 좋아서 (26)
      • Docker가 좋아서 (7)
      • Redis가 좋아서 (7)
      • AWS가 좋아서 (5)
      • CI/CD가 좋아서 (6)
      • Troubleshooting이 좋아서 (4)
      • Kotlin이 좋아서 (7)
      • SQL이 좋아서 (6)
      • HTTP가 좋아서 (21)
      • JavaScript가 좋아서 (30)
      • TypeScript가 좋아서 (6)
      • Vue가 좋아서 (21)
      • Flutter가 좋아서 (61)
      • React가 좋아서 (20)
      • Redux(React)가 좋아서 (2)
      • Angular가 좋아서 (22)
      • HTML이 좋아서 (9)
      • CSS가 좋아서 (15)
      • PHP가 좋아서 (9)
      • Illustrator가 좋아서 (2)
    • 노력이 좋아서 (169)
    • 결과물이 좋아서 (14)
    • 코딩연습이 좋아서 (78)
      • 이론이 좋아서 (62)
      • SQL이 좋아서 (0)
    • 유용한 사이트가 좋아서 (28)
    • Github (2)

인기 글

티스토리

hELLO · Designed By 정상우.
zoaseo

To Infinity And Beyond

개발이 좋아서/Troubleshooting이 좋아서

@WithCustomMockUser - 테스트 코드 작성 시 인증

2025. 2. 24. 17:11

컨트롤러단에서 @AuthenticationPrincipal을 이용해 id값을 가져와 쓰고 있었다.

테스트 코드를 작성하는데 id값을 어떻게 가져와야 할 지 몰랐다. 그래서 @WithCustomMockUser 어노테이션을 만들어 사용하였다.

package com.swyp.libri.domain.annotation;

import org.springframework.security.test.context.support.WithSecurityContext;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithCustomMockUserSecurityContextFactory.class)
public @interface WithCustomMockUser {
    String email() default "test@example.com";
    String role() default "ROLE_USER";
    long id() default 1L;
}
package com.swyp.libri.domain.annotation;

import com.swyp.libri.domain.model.Member;
import com.swyp.libri.global.oauth2.CustomUserPrincipal;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.test.context.support.WithSecurityContextFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.Collections;

public class WithCustomMockUserSecurityContextFactory implements WithSecurityContextFactory<WithCustomMockUser> {

    @Override
    public SecurityContext createSecurityContext(WithCustomMockUser customUser) {
        SecurityContext context = SecurityContextHolder.createEmptyContext();

        Member member = new Member(customUser.email(), "provider", "id");

        ReflectionTestUtils.setField(member, "id", customUser.id());

        CustomUserPrincipal principal = new CustomUserPrincipal(
                member,
                Collections.emptyMap(),
                Collections.singletonList(new SimpleGrantedAuthority(customUser.role()))
        );

        Authentication authentication = new TestingAuthenticationToken(principal, null);
        authentication.setAuthenticated(true);
        context.setAuthentication(authentication);
        return context;
    }
}

 

 

테스트 코드

package com.swyp.libri.domain.controller;

import com.swyp.libri.domain.annotation.WithCustomMockUser;
import com.swyp.libri.domain.auth.dto.UniqueIdRequest;
import com.swyp.libri.domain.model.Member;
import com.swyp.libri.domain.repository.MemberRepository;
import com.swyp.libri.domain.service.MemberService;
import com.swyp.libri.global.oauth2.CustomUserPrincipal;
import com.swyp.libri.global.util.ApiDocumentation;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;

import java.security.Principal;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WithCustomMockUser
@AutoConfigureRestDocs
@WebMvcTest(MemberController.class)
class MemberControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockitoBean
    private MemberService memberService;

    private static final String URL = "/member";
    private static final String TAG = "MEMBER";

    @Test
    void createUniqueId() throws Exception {

        Long memberId = 1L;
        String uniqueId = "unique123";

        doNothing().when(memberService).createUniqueId(memberId, uniqueId);

        ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders.post(URL + "/create/unique-id")
                .content(new ObjectMapper().writeValueAsString(new UniqueIdRequest(uniqueId)))
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .with(csrf().asHeader()));

        actions.andExpect(status().isOk())
                .andDo(ApiDocumentation.builder()
                        .tag(TAG)
                        .description("아이디 생성 API")
                        .requestFields(
                                fieldWithPath("uniqueId").description("생성할 유니크 ID")
                        )
                        .build())
                .andDo(print());

        verify(memberService).createUniqueId(memberId, uniqueId);
    }
}

@WithCustomMockUser로 컨트롤러단에서 테스트 코드를 만들 수 있었다.

'개발이 좋아서 > Troubleshooting이 좋아서' 카테고리의 다른 글

cors 에러 문제 - trim을 안했다..  (0) 2025.03.03
빈 등록 안하고 싶을 때 - @Autowired(required = false)  (0) 2025.02.27
There were failing tests. See the report at: file:///C:/repository/ 프로젝트/build/reports/tests/test/index.html  (0) 2025.02.17

    티스토리툴바