전공공부
Mockito를 사용한 단위 테스트에서 발생하는 다양한 이슈 본문
단위 테스트는 소프트웨어 개발의 중요한 부분입니다. Mockito는 Java에서 단위 테스트를 작성할 때 널리 사용되는 프레임워크 중 하나입니다. 하지만 Mockito를 사용하면서 발생할 수 있는 몇 가지 이슈가 있었고 이를 정리해봤습니다.
문제 : NullPointerException / MockitoException
Cannot invoke "org.springframework.jdbc.core.JdbcTemplate.queryForObject(String, Object[], org.springframework.jdbc.core.RowMapper)" because "this.jdbcTemplate" is null
이 에러는 UserDaoImpl 클래스의 인스턴스가 생성될 때 JdbcTemplate 객체가 주입되지 않아서 발생합니다. UserDaoTest 클래스에서 UserDaoImpl 객체를 생성할 때 JdbcTemplate 객체를 주입해야 합니다.
org.mockito.exceptions.base.MockitoException:
Cannot instantiate @InjectMocks field named 'userDao'! Cause: the type 'UserDao' is an interface.
이 에러는 @InjectMocks 어노테이션이 붙은 필드가 인터페이스 타입이기 때문에 발생합니다. Mockito는 인터페이스의 인스턴스를 생성할 수 없습니다. 따라서 구현체를 불러와서 해결해봅시다.
해결 방법
테스트 클래스를 아래와 같이 수정합니다:
@ExtendWith(MockitoExtension.class)
public class UserDaoTest {
@Mock
private JdbcTemplate jdbcTemplate;
private UserDao userDao;
@BeforeEach
public void setUp() {
userDao = new UserDaoImpl(jdbcTemplate);
}
@Test
public void testUserDao() {
when(jdbcTemplate.queryForObject(anyString(), any(Object[].class), any(RowMapper.class)))
.thenReturn(new User(1L, "John Doe"));
User retrievedUser = userDao.getUserById(1L);
assertThat(retrievedUser).isNotNull();
assertThat(retrievedUser.getName()).isEqualTo("John Doe");
}
}
@BeforeEach 어노테이션이 붙은 setUp 메소드는 각 테스트 메소드가 실행되기 전에 호출됩니다. 이 메소드에서 UserDaoImpl 객체를 생성하고 JdbcTemplate 객체를 주입하고 있습니다. 이렇게 하면 UserDaoImpl 클래스의 메소드를 호출할 때 NullPointerException이 발생하지 않을 것입니다.
@InjectMocks 어노테이션이 제거되었고, UserDao 필드가 UserDaoImpl 타입으로 변경되었습니다. 이렇게 하면 Mockito가 UserDaoImpl 인스턴스를 생성할 수 있습니다.
간단하지만 사실 이런 에러가 왜 생기고 이를 어떻게 처리 할 지에 대해서 상세히 정리해봤습니다. 물론, SpringBootTest를 쓰고 의존성을 추가하면 되지만 그것은 진정한 의미의 단위 테스트가 될 수 없다고 생각합니다. 따라서, 이런 방식을 참고해서 앞으로 테스트 케이스의 작성을 고급지게 할 수 있을 것 입니다.
코드 링크
https://github.com/1ComputerMaster/1ComputerMaster/tree/main/Study/tester
'Study > Spring Boot' 카테고리의 다른 글
[Webflux] Webflux, MVC, Virtual Thread...? (0) | 2024.01.27 |
---|---|
[Spring] Hexagonal Arichtecture - MVC 패턴과 비교하다. (0) | 2024.01.21 |
[Spring] PSA(Portable Service Abstraction) + DI(Dependency Injection) (0) | 2024.01.19 |
[Hexagonal Architecture] 1장. 왜 헥사고날 아키텍쳐를 사용하는가? (0) | 2023.12.09 |
Spring Batch를 이용한 대량의 insert 최적화 (0) | 2023.01.03 |