inflearn logo
강의

Khóa học

Chia sẻ kiến thức

Tạo máy chủ đầu tiên của bạn bằng Java và Spring Boot Bất kỳ ai cũng có thể dễ dàng chuyển từ giai đoạn phát triển sang triển khai! [Gói phát triển máy chủ tất cả trong một]

안녕하세요. 강의 후 개인적으로 학습 시 나타나는 NPE관련 질문드립니다.

Đã giải quyết

371

javabase

8 câu hỏi đã được viết

1

안녕하세요! 강의를 완강 후 혼자 프로젝트를 진행하다 도서 대출 코드를 보고 비슷하게 구현한 사용자가 채용공고를 지원하는 메소드를 호출시 테스트 코드에서 NPE가 발생하는데 혹시 이유를 알 수 있을까요? 여러가지 서칭해봐도 해결이 안되서 질문드립니다... ㅠㅠ

회원entity

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "users")
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ApplyHistory> applyHistory = new ArrayList<>();

    public void applyCompany(JobPosting jobPosting) {
        this.applyHistory.add(new ApplyHistory(this, jobPosting));
    }

    @Builder
    private User(Long id, String name, List<ApplyHistory> applyHistory) {
        this.id = id;
        this.name = name;
        this.applyHistory = applyHistory;
    }

}

ApplyHistory entity(JobPosting과 user객체가 N:M 매핑해주는 entity)

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "apply_history")
@Entity
public class ApplyHistory {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "apply_history_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "job_posting_id")
    private JobPosting jobPosting;

    public ApplyHistory(User user, JobPosting jobPosting) {
        this.user = user;
        this.jobPosting = jobPosting;
    }
}

 

JobPosting Entity

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "job_posting")
@Entity
public class JobPosting {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "job_posting_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id")
    private Company company;

    @Column(name = "posting_position")
    private String position;

    private int compensation; //채용보상금

    @Column(name = "posting_details")
    private String postingDetails;

    @Column(name = "technology_used")
    private String technologyUsed;

    @Builder
    private JobPosting(Company company, String position, int compensation, String postingDetails,
        String technologyUsed) {
        this.company = company;
        this.position = position;
        this.compensation = compensation;
        this.postingDetails = postingDetails;
        this.technologyUsed = technologyUsed;
    }

    public void updateJobPosting(String position, int compensation, String postingDetails,
        String technologyUsed) {
        this.position = position;
        this.compensation = compensation;
        this.postingDetails = postingDetails;
        this.technologyUsed = technologyUsed;
    }
}

 

 

applyService

@RequiredArgsConstructor
@Service
public class ApplyService {

    private final JobPostingRepository jobPostingRepository;
    private final UserRepository userRepository;
    private final ApplyHistoryRepository userJobPostingRepository;

    @Transactional
    public void applyCompany(ApplyCompanyRequest request) {

        // 1. 채용공고 정보 찾기
        JobPosting jobPosting = jobPostingRepository.findById(request.getJobPostingId())
            .orElseThrow(() -> new ResourceNotFoundException("jobPosting", request.getJobPostingId()));

        // 2. 유저 정보 가져오기
        User user = userRepository.findById(request.getUserId())
            .orElseThrow(() -> new ResourceNotFoundException("user", request.getUserId()));

        // 3. 지원 유무 확인
        // 3-1. 지원 중이면 예외 발생
        if (userJobPostingRepository.existsByJobPostingAndUser(jobPosting, user)) {
            throw new IllegalArgumentException("이미 지원하신 회사입니다.");
        }

        user.applyCompany(jobPosting);
    }
}

 

리퀘스트

@Getter
@Setter
public class ApplyCompanyRequest {

    private Long jobPostingId;
    private Long userId;
}

 

서비스 테스트 코드

@SpringBootTest
class ApplyServiceTest {

    @Autowired
    JobPostingService jobPostingService;

    @Autowired
    ApplyService applyService;

    @Autowired
    JobPostingRepository jobPostingRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    ApplyHistoryRepository applyHistoryRepository;

    @Autowired
    CompanyRepository companyRepository;

    @AfterEach
    void tearDown() {
        applyHistoryRepository.deleteAllInBatch();
        jobPostingRepository.deleteAllInBatch();
        userRepository.deleteAllInBatch();
        companyRepository.deleteAllInBatch();
    }

    @DisplayName("사용자는 채용 공고를 지원 할 수 있다.")
    @Test
    @Transactional
    void applyCompany() {
        //given
        User user = User.builder()
            .id(1L)
            .name("jw")
            .build();

        User savedUser = userRepository.save(user);

        Company company = Company.builder()
            .name("company1")
            .country(Country.KOREA)
            .city(City.SEOUL)
            .build();
        Company savedCompany = companyRepository.save(company);

        JobPosting jobPosting = JobPosting.builder()
            .company(savedCompany)
            .position("백엔드")
            .postingDetails("백엔드 개발자 채용합니다.")
            .compensation(500000)
            .technologyUsed("Java")
            .build();

        JobPosting savedJobPosting = jobPostingRepository.save(jobPosting);

        ApplyCompanyRequest request = new ApplyCompanyRequest();
        request.setUserId(savedUser.getId());
        request.setJobPostingId(savedJobPosting.getId());

        //when
        applyService.applyCompany(request);

        //then


    }

}

 

-> 이부분에서 applyCompany(request) 호출 시 NPE가 발생합니다.

java.lang.NullPointerException
	at com.wanted.findjob.domain.user.User.applyCompany(User.java:36)
	at com.wanted.findjob.api.service.ApplyService.applyCompany(ApplyService.java:39)
	at com.wanted.findjob.api.service.ApplyService$$FastClassBySpringCGLIB$$2f4064b0.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
	at com.wanted.findjob.api.service.ApplyService$$EnhancerBySpringCGLIB$$81701d47.applyCompany(<generated>)
	at com.wanted.findjob.api.service.ApplyServiceTest.applyCompany(ApplyServiceTest.java:83)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

 

테스트코드가 아닌 직접 서버를 작동해서 api를 호출 시 정상적으로 db에 들어가는 걸 볼 수 있는데 어디가 문제 인지를 모르겠습니다.. ㅠ

java spring aws mysql spring-boot jpa

Câu trả lời 2

1

javabase

User Entity에서 Bulider패턴 사용시 List<ApplyHistory> applyHistory 초기화 부분문제 때문에 일어난 거였습니다.. 혹시라도 비슷한 경험을 하시는 분들을 위해 질문은 남겨 놓을게요 감사합니다!

0

lannstark

안녕하세요 정우님!! 와우~ 해결하셨군요!! 다행입니다~ 😊

 

추가적으로 테스트를 하다가 뭔가 동작이 이상하면

DB의 데이터를 확인해보실 수 있습니다.

 

예를 들어, 테스트 중간에 ApplyHistoryRepository에 접근해보는 것이죠!

 

혹시나 또 어려운 점 있으시면 편하게 질문 남겨주세요.

감사합니다! 🙇

2

javabase

친절한 답변에 링크 영상까지 정말 감사합니다.!!

패키지 구분에 대해 궁금한게 있습니다

0

13

1

리액트 관련 질문이 있습니다.

0

63

2

스프링부트 버전

0

69

2

7강 강의를 들으려고 했는데 오류가 나서 서버가 안 켜지는거 같아요.

0

57

2

33강. UserLoanHistory의 관계성에 대한 질문

1

55

2

Java JDK 버전 문의의 건

0

132

2

ec2 에서 Linux버전이 달라져서 설치가 안되는것 같은데 자료 최신화좀 해주세요.

0

85

3

h2 console 접속했을 테이블 질문

1

64

1

ec2 서버에서 스프링 실행도 되고 인바운드 설정까지 했는데 index.html 안됨

0

74

2

15강. updateUser() 질문

0

55

2

깃허브 질

0

81

2

여기까지 다 끝냈다고 하셨는데

0

78

2

왜안될까요

0

69

2

MySQL 창이안ㄴ뜹니다

0

58

2

포스트맨

0

49

1

spring 개념적인 질문

0

71

2

인텔리제이 샘플코드 실행 안됨 오류

0

139

2

aws 배포할때 .env 파일에 저장한 환경변수에 관하여 여쭤볼게 있습니다

0

82

1

마이그레이션 오류입니다.

0

169

3

Whitelabel Error Page 오류가 났습니다.

0

162

2

안녕하십니까! 오류가 났습니다.. 도와주세요 ㅜㅜ

1

90

3

궁금한게 있습니다.

0

57

2

DTO 관련

0

69

2

궁금한게 있습니다!

0

65

2