BottomNavigationView는 디자인 라이브러리 버전 25부터 사용할 수 있는 컴포넌트입니다. UX에서 끊임없이 토론( [1] [2] [3] )되고 있는 햄버거 메뉴에 대응하는 직관적인 UI컴포넌트이고, 심지어 머테리얼 디자인 가이드에도 포함되어 있습니다.

디자인 가이드에 따르면 BottomNavigationView는 3~5개의 메뉴를 표현하는 데 적합하고, 또한 menu resource로 내용을 표현하므로 어느 정도 계층을 분리하여 잘 설계된 컴포넌트로 보입니다. 나온지 얼마되지 않았기에 ButterKnifeRobolectric에서 이에 대한 지원이 아직은 없습니다. 하지만 Robolectric에서는 커스텀 섀도우 클래스 확장을 지원하기 때문에 이를 이용하여 테스트가 가능합니다.

위와 같이 BottomNavigationView가 포함된 액티비티가 있을 때, 테스트를 고려해보면 다음과 같은 두 가지 사항이 필요합니다.

  1. 현재 내비게이션에 선택된 메뉴 아이템이 무엇인지 알아내기
  2. 내비게이션에서 원하는 메뉴 아이템을 선택하기

이 두 가지 기능이 실제 클래스에 코드로 구현할 수 없기에 다음과 같이 섀도우 클래스가 필요합니다.

원하는 기능을 구현하기 위해 여러 방법이 있겠지만, 저는 MenuBuilder에 있는 아이템들을 뒤져서 체크되어있는 녀석만 골라서 그 아이템을 꺼내는 식으로 구현하였습니다. 덕분에 안드로이드 소스를 통째로 뒤졌지만, 내부적으로 toggle하는 방식으로 구현되어 있어 안전해보입니다. 두번째도 내부적으로는 지정된 리스너로 선택된 아이템을 트리거 해주는 로직이 있는데 실제 구현체로 이 기능을 전달하기에 private으로 선언되어 노출되지 않는 문제 등 여러가지로 인해 리스너를 지정할 때 섀도우 클래스에서 캐치하여 따로 갖고 있고, 나중에 선택하는 시점에 이 리스너를 트리거 해주는 방식으로 구현하였습니다.

테스트 코드는 원하는 상황에 맞게 구현할 수 있었고, 주의해야할 점은 @Config 어노테이션에 방금 만든 섀도우 클래스를 지정해야 하고, 테스트케이스에서 뷰를 꺼낼 때 캐스팅이 필요합니다.