컨트롤러를 만들어서 Testcase 를 작성한 후에 성공할거라 믿고 돌려봤는데 IllegalArgumentException 이 발생했다.
컨트롤러 코드와 테스트 케이스 코드는 각각 다음과 같다.
UserController.java
1 2 3 4 5 6 | @GetMapping(value = "/users/{email}") public UserDto.Res getUser(@PathVariable @Valid final String email){ Optional<Users> users = userService.findByEmailValue(email); return new UserDto.Res(users.get()); } | cs |
UserControllerTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Before public void setUp(){ users = Users.builder() .email(Email.builder().value("test@test.com").build()) .firstName("TEST") .lastName("KIM") .password("password") .build(); } @Test public void getUserTest() throws Exception { given(this.userController.getUser("test@test.com")).willReturn(new UserDto.Res(this.users)); ResultActions resultActions = this.mockMvc.perform( get("/users/{email}", "test@test.com")) .andDo(print()); resultActions .andExpect(jsonPath("firstName").value("TEST")) .andExpect(jsonPath("lastName").value("KIM")) .andExpect(MockMvcResultMatchers.status().isOk()); } | cs |
Exception
Caused by: java.lang.IllegalArgumentException: Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
대체 뭐지??? 맞게 parameter 도 넘겼는데 왜 못찾는거지....
Spring Document 를 보니 다음과 같은 내용을 찾을수 있었다.
The matching of method parameter names to URI Template variable names can only be done if your code is compiled with debugging enabled. If you do have not debugging enabled, you must specify the name of the URI Template variable name to bind to in the @PathVariable annotation.
<출처 : https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch18s02.html >
컴파일 할때 debugging enabled 가 되어야 동작을 하는데 그렇지 않을 경우에는 반드시 @PathVariable 사용시 name 에 값을 줘야 한다고 되어있다.
그럼 컴파일 할때 debugging enabled 는 뭔가?? -_-;;
java 소스를 컴파일할때 사용되는 javac 명령어를 찾아보면 다음과 같은 옵션이 있다. 컴파일시에 -g 옵션을 사용할 경우 로컬 지역변수(local variables) 를 포함한 debugging information 을 생성하고 디폴트로는 라인 넘버와 소스파일 정보만 생성된다고 써있다.
- source
- Source file debugging information
- lines
- Line number debugging information
- vars
- Local variable debugging information
<출처 : https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html>
그럼 간단한 자바 클래스를 컴파일 해서 확인해보자.
1 2 3 4 5 6 | public class Test { public static void main (String[] args) { String name = "test"; System.out.println(name); } } | cs |
javac Test.java (옵션 없이 할경우)
1 2 3 4 5 6 7 8 9 10 11 12 13 | # javap -l Test Compiled from "Test.java" public class Test { public Test(); LineNumberTable: line 4: 0 public static void main(java.lang.String[]); LineNumberTable: line 6: 0 line 7: 3 line 8: 10 } | cs |
javac -g Test.java (-g 옵션을 붙여서 할경우)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # javap -l Test Compiled from "Test.java" public class Test { public Test(); LineNumberTable: line 4: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LTest; public static void main(java.lang.String[]); LineNumberTable: line 6: 0 line 7: 3 line 8: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 args [Ljava/lang/String; 3 8 1 name Ljava/lang/String; } | cs |
각각의 경우를 javap 명령어로 확인해 보았다. (javap 명령어는 컴파일된 class 파일을 역 어셈블 해주는 명령어 있다. -l 옵션을 붙이면 로컬변수 테이블까지 보여준다.)
첫번째에서는 기본적으로 라인만 보이는데 두번째에서는 로컬 변수까지 다 보여준다.
결론적으로 맨 처음 Testcase 에서 발생했던 문제는 UserController.java 를 컴파일 했을때 -g 옵션이 안들어가서 컴파일 후에 @PathVariable 에 있는 변수를 못찾아서 발생한 문제였다. 이게 IntelliJ 에서 따로 compile 옵션설정을 해야 할지는 잘 모르겠는데 나는 @PathVariable 에 name 을 명시해주는 방법으로 해결을 했다.
참고자료
https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/spring-path-variable.html
https://objectpartners.com/2010/08/12/spring-pathvariable-head-slapper/
https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/parameter-name-discoverer.html
'Development > Java' 카테고리의 다른 글
[SpringBoot] @RequestBody 에 들어가는 Object 는 No-Argument Constructor 가 존재해야 한다. (0) | 2019.10.21 |
---|---|
[Spring Boot] There is no PasswordEncoder mapped for the id "null" (0) | 2019.09.09 |
java.util.Date 쓰다 삽질한 내용.... (0) | 2019.01.25 |
[SpringBoot] Properties 우선순위 (0) | 2018.06.07 |
[SpringSecurity]Spring Reference 수정 (0) | 2018.04.21 |