Refactor : Adjust resolveFieldName Method Logic to Correctly Handle Primitive boolean Field Names#1096
Conversation
| public String resolveFieldName(Class<?> targetClass, String methodName) { | ||
| if (hasPrefix(GET_PREFIX, methodName)) { | ||
|
|
||
| if (isValidField(targetClass, methodName)) { |
There was a problem hiding this comment.
하위호환을 보장하고 안전하게 변경됨을 보장하기 위해 다음 테스트들이 추가되면 좋을 것 같습니다.
is가 이름의 prefix로 붙은 boolean이 아닌 필드를 setis가 이름의 prefix로 붙지않은 boolean의 필드를 setis가 이름의 prefix로 붙은 boolean인 필드를 setis가 이름의 prefix로 붙지않은 boolean이 아닌 필드를 set
There was a problem hiding this comment.
테스트 추가했습니다!
- is가 이름의 prefix로 붙은 boolean이 아닌 필드를 set
- is가 이름의 prefix로 붙지않은 boolean의 필드를 set
- is가 이름의 prefix로 붙은 boolean인 필드를 set
- is가 이름의 prefix로 붙지않은 boolean이 아닌 필드를 set
추가로 Boolean 필드가 Wrapper Type일 경우와 Primitive Type일 경우의 테스트도 작성했습니다.
|
|
||
| @Test | ||
| void testNonBooleanFieldWithIsPrefix() { | ||
| assertDoesNotThrow(() -> { |
There was a problem hiding this comment.
다른 테스트들을 보고 컨벤션을 맞춰주시면 좋을 것 같습니다.
|
|
||
| import com.navercorp.fixturemonkey.api.expression.JavaGetterPropertyFieldNameResolver; | ||
|
|
||
| public class JavaGetterPropertyFieldNameResolverTest { |
There was a problem hiding this comment.
License를 추가하고, public을 제거하면 좋을 것 같습니다.
|
|
||
| public class JavaGetterPropertyFieldNameResolverTest { | ||
|
|
||
| private final JavaGetterPropertyFieldNameResolver resolver = new JavaGetterPropertyFieldNameResolver(); |
There was a problem hiding this comment.
테스트 대상을 식별하기 편하게 하기 위해 sut라고 이름을 짓는 게 좋은 것 같습니다.
| Method method = TestClass.class.getDeclaredMethod("getIsStatus"); | ||
|
|
There was a problem hiding this comment.
reflection을 사용해서 내부 구현을 테스트하는 방향은 테스트를 깨지기 쉽게 만듭니다.
아래 글에서 제안하는 것처럼 public API를 통해 테스트하는 방향으로 변경하면 좋을 것 같습니다.
https://testing.googleblog.com/2015/01/testing-on-toilet-prefer-testing-public.html
아래 예제를 참고해보는 것도 좋을 것 같습니다.
There was a problem hiding this comment.
말씀하신대로 내부 구현에 대한 테스트에서 생성자 기반의 public API 테스트로 변경했습니다. 추가로 @RepeatedTest(TEST_COUNT) 를 적용한 반복 테스트 검증도 진행했습니다.
| } | ||
|
|
||
| @Getter | ||
| private static class TestClass { |
There was a problem hiding this comment.
이름이 더 구체적이면 좋을 것 같습니다.
JavaGetterObject 라고 바꾸면 javaGetter를 테스트하기 위한 용도로 이해할 수 있을 것 같습니다.
| @RepeatedTest(TEST_COUNT) | ||
| void testNonBooleanFieldWithIsPrefix() { | ||
| thenCode(SUT.giveMeBuilder(JavaGetterObject.class) | ||
| .set(javaGetter(JavaGetterObject::getIsStatus), "javaGetterStringStatus")::sample) |
There was a problem hiding this comment.
set 같은 연산이 정상적으로 동작했는지 검증하는 게 좋을 것 같습니다.
ex. then(actual.getIsStatus()).isEqualTo("javaGetterStringStatus")
There was a problem hiding this comment.
검증 테스트 추가 완료했습니다!
Summary
JavaGetterPropertyFieldNameResolver의resolveFieldName메소드가 필드 값을 추출하는 과정에서,원시 타입
boolean필드값 추출 시 올바른 필드명이 추출되지 않아 메소드 순서를 변경했습니다.Description
Lombok의@Getter어노테이션을 사용할 때,boolean타입을primitive type으로 설정하고, 필드명의 prefix를“isXXX”로 사용하는 경우 문제가 있습니다.위와 같은 엔티티에서 boolean isUsed; 라는 필드가 있다고 가정할 때,
Lombok 은 위처럼 필드명과 동일한

getter를 생성합니다. (Sample::isUsed)하지만
JavaGetterPropertyFieldNameResolver의resolveFieldName메소드에서,else if (hasPrefix(IS_PREFIX, methodName))가true일 경우stripPrefixPropertyName(targetClass, methodName, IS_PREFIX.length())를 수행하기 때문에,isUsed필드명이used로 strip되어 resolve되기에 NPE 에러가 발생합니다.위처럼
isValidField(targetClass, methodName)검증을 가장 먼저 수행하도록 변경하면, 필드명과 메소드명이 동일한 경우에도 대응이 가능해 변경했습니다.How Has This Been Tested?
Passed All Existing Tests