본문 바로가기

Develop/Springboot

QueryDSL 슬라이싱 테스트(@DataJpaTest) / Test Bean 등록

QueryDSL 슬라이싱 테스트 방법에 대해 기록을 남긴다.

내가 주로 사용하는 Querydsl 패턴은 CustomRepository를 만드는 방식이다.

docs.spring.io/spring-data/jpa/docs/2.1.3.RELEASE/reference/html/#repositories.custom-implementations

 

Spring Data JPA - Reference Documentation

Example 100. Using @Transactional at query methods @Transactional(readOnly = true) public interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") v

docs.spring.io

코드는 아래와 같다.

public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
    Optional<User> findByEmail(String email);
}
public interface UserRepositoryCustom {
    Optional<User> findByUserId(Long userId);
}
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepositoryCustom {

    private final JPAQueryFactory jpaQueryFactory;

    @Override
    public Optional<User> findByUserId(Long userId) {
        User user = jpaQueryFactory.selectFrom(QUser.user)
                .where(QUser.user.userId.eq(userId))
                .fetchOne();
        return Optional.ofNullable(user);
    }
}

 

이렇게 짠 Querydsl 코드를 테스트하기 위한 테스트코드를 짤 때 @SpringBootTest를 하면 모든 빈이 주입되기 때문에 상관이 없지만,

아래 코드와 같이 DataJpaTest와 같은 슬라이싱 테스트를 하고싶을 때 문제가 발생한다.

@DataJpaTest
@ActiveProfiles("test")
class UserRepositoryTest {

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private UserRepository userRepository;

    private User settingUser() {
        User settingUser = User.builder()
                .email("jyami@ewhain.net")
                .name("jyami")
                .build();

        return userRepository.save(settingUser);
    }

    @Test
    void test() {
        settingUser();
        entityManager.clear();
        User user = userRepository.findByUserId(1L)
                .orElseThrow(() -> new ResourceNotFoundException("user", "userId", 1L));
    }



}
Error creating bean with name 'userRepositoryImpl' defined in file [/Users/jyami/Documents/commiters/commiters-ewha/commiters-ewha-api/build/classes/java/main/com/jyami/commitersewha/domain/user/UserRepositoryImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.querydsl.jpa.impl.JPAQueryFactory'

결국 이유는 JpaQueryFactory가 persistenceLayer가 아니어서 빈등록이 되지않아 발생하는 문제인데, 
이때 테스트 시 특정부분의 빈만 등록해주는 방법이 있었다!

@TestConfiguration
public class TestConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

테스트에서만 사용할 용도의 @TestConfiguration을 이용해 JPAQueryFactory 만 Bean으로 생성해준다.

@DataJpaTest
@ActiveProfiles("test")
@Import(TestConfig.class)
public class UserRepositoryTest {
}

 

이후 @Import 어노테이션을 사용해 해당 테스트용 빈을 주입해주면, JpaQueryFactory에 대한 빈도 생성되므로, Querydsl의 슬라이싱 테스트가 가능해진다 :)


도움: github.com/jojoldu/blog-comments/issues/277#issuecomment-702597745