이 포스팅은 신선영 저, 『스프링 부트 3 백엔드 개발자 되기』(골든래빗, 2023)를 공부하면서 마주한 에러 및 버그를 해결하는 과정을 기록하기 위해서 작성되었습니다.
java.lang.AssertionError: Status expected:<201> but was:<404>
Expected :201
Actual :404

'9장. JWT로 로그인/로그아웃 구현하기'에서, 리프레쉬 토큰을 받아서 새로운 엑세스 토큰을 발급하는 API의 테스트 코드를 실행시켰을 때에 마주한 에러였다.
스테이터스 코드가 404가 나왔다는 것은 존재하지 않는 자원의 url에 접근을 시도했다는 의미다. 그래서 url 주소의 오타를 가장 먼저 확인했다.
컨트롤러(TokenApiController.java)에 적힌 url은 "/api/token"이었다.
@RequiredArgsConstructor
@RestController
public class TokenApiController {
private final TokenService tokenService;
@PostMapping("/api/token")
public ResponseEntity<CreateAccessTokenResponse> createNewAccessToken(
@RequestBody CreateAccessTokenRequest request) {
String newAccessToken = tokenService.createNewAccessToken(request.getRefreshToken());
return ResponseEntity.status(HttpStatus.CREATED)
.body(new CreateAccessTokenResponse(newAccessToken));
}
}
테스트코드(TokenApiController.java)에 적힌 url 역시 "/api/token"으로 컨트롤러의 url과 일치했다.
@SpringBootTest
@AutoConfigureMockMvc
public class TokenApiController {
// 생략 //
@DisplayName("createNewAccessToken: 새로운 엑세스 토큰을 발급한다.")
@Test
public void createdNewaccessToken() throws Exception{
// given
final String url = "/api/token";
User testUser = userRepository.save(User.builder()
.email("user@gmail.com")
.password("test")
.build());
// 생략 //
}
따라서 가설 1은 에러의 원인이 아니었다.
WebSecurityConfig.java에서 별도의 인증 및 인가 없이 접근할 수 있는 url들과 인증을 해야만 접근할 수 있는 url들을 설정해주었다. 그래서 로그인과 회원가입 따위의 url을 제외한 모든 url은 테스트 환경의 모킹된 MVC구조에서조차 접근할 수 없게 된 것이 아닐까 하는 생각이들었다.
그래서 이전에 작성한 블로그 글을 작성하고 수정하는 url에 접속하여 테스트를 돌리는 테스트 코드(BlogApiControllerTest.java)를 다시 실행시켜보았다. 이 가설이 맞다면 이 테스트 코드에서도 통과가 되지 않아야 할 것이다.

이 테스트 코드의 모든 테스트가 무사히 통과가 된 것을 보아하니, 스프링 시큐리티의 설정 때문은 아닌 것으로 보인다. 가설 2는 에러의 원인이 아니었다.
이 두가지 가설 외에 내가 떠올릴 수 있는 가설은 더이상 없었다. 하염없이 코드만을 쳐다보고 있던 도중, 문뜩 에러가 난 테스트 코드의 클래스 이름에 노란색 밑줄이 쳐져 있는 것이 눈에 들어왔다.

Test class name 'TokenApiController' doesn't match regex '[A-Z][A-Za-z\d]*Test(s|Case)?|Test[A-Z][A-Za-z\d]*|IT(.*)|(.*)IT(Case)?'
TokenApiController라는 클래스 명이 이러한 정규식과 일치하지 않는다는 의미인 듯 보였다. 그러고보니 다른 테스트 코드를 돌리기 위한 클래스의 이름은 모두 "~~Test"로 끝났다. 그런데 이 클래스는 그렇지 않았다.
그래서 클래스 이름을 TokenApiControllerTest로 변경하고 다시 테스트를 돌려보았다.

클래스 이름만 바꿔주었을 뿐인데 테스트가 통과되었다!
아무래도 스프링 부트는 많은 기능들이 자동으로 동작한다. 클래스와 변수들을 자동으로 감지해서 동작하기 위해서는 클래스와 변수 이름들을 규칙에 맞게 꼼꼼히 지어야 할 것이다. 테스트 코드의 클래스 이름도 이 경우에 속할 줄은 전혀 몰랐다. 다음부터는 이름을 지을 때에 좀 더 주의해야겠다.