반응형
심화 과제로 테스트 코드 작성을 했었는데 처음 하는 거다 보니 어떻게 적어야 할지 몰라서 조금 헤맸다. 정답이 딱 정해진 게 아니다 보니 구글링으로 레퍼런스로 찾기도 힘들어서 더 그랬다. 그래서 해설 강의와 레포를 보면서 다시 개선해보고 있다.
그중 하나로 컨트롤러 테스트마다 @WebMvcTest를 달아주어 매 컨트롤러마다 스프링을 실행하던 것을 부모 클래스로 추상화하여 상속을 받도록 했다. 사실 이건 ㅊㅈㅇ님께서 알려준 내용이지만.
@ActiveProfiles("test")
@MockBean(JpaMetamodelMappingContext.class)
@WebMvcTest(
controllers = {
AuthController.class,
TodoController.class,
CommentController.class
},
excludeFilters = {
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = WebSecurityConfig.class
)
}
)
public abstract class ControllerTest implements UserTest { // 그냥 클래스로 하면 테스트의 대상이 되어 추상 클래스.
@Autowired
private WebApplicationContext context;
@Autowired
protected MockMvc mvc;
@Autowired
protected ObjectMapper objectMapper;
protected Principal mockPrincipal;
@MockBean
protected AuthService authService;
@MockBean
protected CommentService commentService;
@MockBean
protected TodoCardService todoCardService;
@MockBean
protected UserRepository userRepository;
@MockBean
protected TodoCardRepository todoCardRepository;
@BeforeEach
void setUp() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity(new MockSpringSecurityFilter()))
.alwaysDo(print())
.build();
// Mock 테스트 UserDetails 생성
CustomUserDetails userDetails = new CustomUserDetails(TEST_USER);
// SecurityContext 에 인증된 사용자 설정
var authentication = new UsernamePasswordAuthenticationToken(
userDetails, userDetails.getPassword(), userDetails.getAuthorities());
this.mockPrincipal = authentication;
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
@WebMvcTest 내에 controllers로 모든 테스트 대상 컨트롤러를 설정해 두고, 이 클래스에서만 쓰이는 WebApplicationContext는 private으로 하고, @MockBean으로 각 컨트롤러에서 쓰이는 서비스와 레포지토리를 모두 선언해 둔다. (생각해 보니 레포지토리는 왜 있지 싶은데 나중에 고치기로 하고)
원래 var 를 싫어하는 편인데 authentication의 타입인 UsernamePasswordAuthenticationToken은 너무 길어서 써주었다.
public interface UserTest {
Long TEST_USER_ID = 1L;
Long ANOTHER_TEST_USER_ID = 2L;
String TEST_USER_NAME = "username";
String TEST_USER_PASSWORD = "12345678";
String TEST_ANOTHER_USER_NAME = "another-";
String TEST_ANOTHER_USER_PASSWORD = "12345678";
User TEST_USER = User.createUser(TEST_USER_NAME, TEST_USER_PASSWORD);
User TEST_ANOTHER_USER = User.createUser(TEST_ANOTHER_USER_NAME, TEST_ANOTHER_USER_PASSWORD);
}
TEST_USER의 경우는 이렇게 인터페이스로 선언해 두어서 테스트마다 일일이 유저를 만들어주지 않도록 했다.
@DisplayName("인증 컨트롤러 테스트")
class AuthControllerTest extends ControllerTest {
// ...
}
그리고 이렇게 상속을 받아서 특정 컨트롤러에 대한 내용을 @DisplayName 으로 설명을 달아주고 @BeforeEach 도 없이 그냥 테스트를 작성해 주면 된다.
반응형
'TIL ✍️' 카테고리의 다른 글
23년 12월 6일(수요일) - 46번째 TIL (0) | 2023.12.06 |
---|---|
23년 12월 5일(화요일) - 45번째 TIL : AOP (1) | 2023.12.05 |
23년 12월 1일(금요일) - 43번째 TIL : validation 검증하기 (0) | 2023.12.01 |
23년 11월 30일(목요일) - 42번째 TIL (0) | 2023.11.30 |
23년 11월 29일(수요일) - 41번째 TIL (1) | 2023.11.29 |