최근 테스트 케이스를 만들다가 자료 구조의 Mutability 때문에 고생을 한적이 있습니다. 결과를 먼저 얘기하자면 Immutable한 자료구조를 사용해서 이런 결과가 있었기 때문이었죠. 이 이슈의 Root cause는 코드 Implementation에는 ArrayList를 사용하고 테스트 케이스를 만들 때 mock list를 "List.of"를 사용했기 때문이죠. 왜 이런 이슈가 생긴걸까요?
List.of()
List.of()를 선언하고 class type을 본다면 뭐가 나올까요? ArrayList? LinkedList? 답을 말 하자면 둘 다 아닙니다. ArrayList와 LinkedList는 Collection 프레임워크의 Interface로서 객체를 insert, delete and update를 할 수 있습니다. 다시 말해서 가변성을 가지고 있는 Interface죠. 하지만 List.of()는 이 가변성을 따르지 않습니다.
공식 문서에 따르면 정적인 factory methods인 List.of()는 불가변적인 리스트를 만들수 있도록 도와줍니다. 그리고 다음과 같은 특징들을 가지고 있습니다.
- 불가변성. 새로운 element들이 추가, 삭제, 교체 될수가 없고 mutator method를 사용하면 "UnsupportedOperationException"이 thrown 됩니다.
- Null element들이 사용될 수 없습니다.
- 모든 elements가 직렬화가 된다면 List.of()도 직렬화가 됩니다.
- Elements의 순서는 패스된 Argument에 쓰여진대로 정해집니다.
- Value-based로 이루어져있습니다.
- Serialized Form page 서술된 대로 직렬화가 되어있습니다.
Conclusion
List Interface와 다르게 List.of() 자체는 Immutability(불가변성)을 가지고 있어서 앞으로 테스트 케이스를 만들때 조심해야되는 부분인것 같습니다. 만약에 List.of 대신 mutable(가변성)을 가지고 initialize를 하고 싶으시면 아래와 같이 하면 될 것 같습니다.
List<Integer> list = new ArrayList<Integer>() {{
add(1);
add(3);
}};
References
1. https://docs.oracle.com/javase/9/docs/api/java/util/List.html#of-E...-
2. https://www.geeksforgeeks.org/initializing-a-list-in-java/
'Java' 카테고리의 다른 글
[Stream API] map과 flatMap (0) | 2023.08.21 |
---|---|
오버라이딩(Overriding) vs. 오버로딩(Overloading) (0) | 2022.01.13 |
객체(Object)란 무엇일까요? (0) | 2020.04.25 |