인프런 커뮤니티 질문&답변

윤건희님의 프로필 이미지
윤건희

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

회원 기능 테스트

MemberServiceTest 이게 왜 틀리죠?

작성

·

44

·

수정됨

0

package jpabook.jpashop.service;

import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;


//@ExtendWith(SpringExtension.class) //@SpringBootTest에 이미 정의됨.(중복)
@SpringBootTest
@Transactional
class MemberServiceTest {

    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

    @Test
    public void 회원가입()throws Exception{
        //given
        Member member=new Member();
        member.setUsername("kim");
        //when
        Long savedId = memberService.join(member);
        //then
        Assertions.assertThat(member).isEqualTo(memberRepository.findOne(savedId));
    }

}

junit 5 버전이라 이렇게 고쳤는데도 테스트에 실패합니다.

 

setUsername은 구버전 MemberRepository에서 오류가 나서 Member의 name을 username으로 바꿨습니다.
test/resources/application.yml에

spring:
  logging.level:
    org.hibernate.SQL:debug

이것도 넣어줬는데 안됩니다

답변 1

0

안녕하세요. 윤건희님, 공식 서포터즈 y2gcoder입니다.

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

실제 동작하는 전체 프로젝트를 ZIP파일로 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx


주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요


추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명 (오류 화면, 오류 로그 포함)


링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

윤건희님의 프로필 이미지
윤건희
질문자

https://drive.google.com/file/d/1XYU4QN9zO5nphBXNf-PTd4Ph7xbleio7/view?usp=sharing


1) test/jpabook/jpashop/service/MemberServiceTest.java 실행하면 됩니다.
2)
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

2024-11-27T15:33:29.929+09:00 INFO 11428 --- [ main] p6spy : #1732689209929 | took 0ms | rollback | connection 4| url jdbc:h2:mem:0f23e7e7-05f2-4edd-b11b-02a2cb3a88d3

;

java.lang.NullPointerException: Cannot invoke "jakarta.persistence.EntityManager.createQuery(String, java.lang.Class)" because "this.em" is null

at jpabook.jpashop.repository.MemberRepository.findByName(MemberRepository.java:44)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:568)

at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)

at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)

at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720)

at jpabook.jpashop.repository.MemberRepository$$SpringCGLIB$$0.findByName(<generated>)

at jpabook.jpashop.service.MemberService.validateDuplicateMember(MemberService.java:51)

at jpabook.jpashop.service.MemberService.join(MemberService.java:43)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.base/java.lang.reflect.Method.invoke(Method.java:568)

at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)

at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)

at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)

at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720)

at jpabook.jpashop.service.MemberService$$SpringCGLIB$$0.join(<generated>)

at jpabook.jpashop.service.MemberServiceTest.회원가입(MemberServiceTest.java:26)

at java.base/java.lang.reflect.Method.invoke(Method.java:568)

at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)



윤건희님의 프로필 이미지
윤건희
질문자

해결했습니다~

보내주신 코드 살펴봤습니다!

  1. EntityManager em = null 해결: @PersistenceContext 를 통해 주입하던 em을 롬복 @RequiredArgsConstructor 를 통한 생성자 주입으로 바꾸셨습니다. 해당 방법은 not null인 필드에 한해서만 생성자를 자동으로 만들어주게 됩니다. not null 인 필드가 되려면 대상 필드에 @NonNull 이 붙어있거나 final 키워드가 붙어 있어야 합니다!

    @Repository //스프링빈으로 등록(@Component가 들어있어서 컴포넌트 스캔대상)
    @RequiredArgsConstructor
    public class MemberRepository {
    
        //스프링이 EntityManger를 만들어서 여기다 주입(Injection)해줌
        //스프링이 생성한 JPA의 엔티티 매니저를 지가 여기다 주입해줌
    //    @PersistenceContext //Service와 마찬가지로 @RequiredArgsConstructor쓰면 영속성 컨텍스트 생략가능
    //    private EntityManager em; // 기존
        private final EntityManager em; // TODO final 키워드를 추가해주세요!
    ...
    }

     

  2. Member entity 와 필드 일치: username으로 변경해주셨다면 MemberRepository의 findByName에 있는 JPQL 에서의 m.name 도 m.username 으로 바꿔주세요!

    public List<Member> findByName(String name) {
            return em.createQuery("select m from Member m where m.username= :name", Member.class)
                    .setParameter("name", name)
                    .getResultList();
        }

     

이렇게 해주시면 테스트가 통과하게 됩니다!

image.png

 

감사합니다!

 

윤건희님의 프로필 이미지
윤건희

작성한 질문수

질문하기