강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của nhs0912
nhs0912

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

Cách giải quyết các vấn đề đồng thời bằng hệ thống kiểm kê

Hãy thử khóa bi quan

Pessimistic Lock 전체 테스트 오류 문의

Viết

·

328

0

안녕하세요.

Pessimistic Lock 소스에서 각각의 테스트 하나하나는 통과하는데요.

테스트 코드 전체로 돌리면 에러가 나더라고요.

 

public interface StockRepository extends JpaRepository<Stock, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select s from Stock s where s.id = :id")
    Stock findByIdWithPessimisticLock(@Param("id") Long id);
}

 

StockServiceTest.java

package com.example.stock.service;

import com.example.stock.domain.Stock;
import com.example.stock.repository.StockRepository;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
class StockServiceTest {

    @Autowired
    private PessimisticLockStockService stockService;
    @Autowired
    private StockRepository stockRepository;

    @BeforeEach
    public void before() {
        stockRepository.saveAndFlush(new Stock(1L, 100L));
    }

    @AfterEach
    public void after() {
        stockRepository.deleteAll();
    }

    @Test
    @DisplayName("재고1개 감소 테스트")
    public void 재고감소() {
        stockService.decrease(1L, 1L);

        //100 - 1 = 99
        Stock stock = stockRepository.findById(1L).orElseThrow();

        assertThat(stock.getQuantity()).isEqualTo(99L);
    }

    @Test
    @DisplayName("동시에 100개 요청 테스트")
    public void 동시에_100개_요청() throws InterruptedException {
        int threadCount = 100;
        ExecutorService executorService = Executors.newFixedThreadPool(32);
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            executorService.submit(() -> {
                try {
                    stockService.decrease(1L, 1L);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        Stock stock = stockRepository.findById(1L).orElseThrow();
        assertThat(stock.getQuantity()).isEqualTo(0L);
    }
}
image.png

이런 오류가 나는데 @BeforeEach에서 새로 등록하고

@AfterEach에서 delete를 해줘서 각각의 테스트에 영향이 없을거 같은데 왜 나는지 잘 모르겠어요 ㅠ

 

 

github : https://github.com/nhs0912/stock

javatestjunitpessimisticlock

Câu trả lời 3

0

169developer9973님의 프로필 이미지
169developer9973
Người chia sẻ kiến thức

HeeSeok Noh 님 안녕하세요.

1) 데이터베이스의 설정이 auto_increment 로 되어있기때문에 그럴겁니다.

2) 테스트를 시작하기전에 findByFirst 를 하여 id 를 얻어온 후 그 값을 사용하면 될것같습니다.

감사합니다.

0

nhs0912님의 프로필 이미지
nhs0912
Người đặt câu hỏi

질문 검색 해보니 다른 답변에서 테스트를 2개 돌리면 Auto_increment 때문에 두번째 테스트에서 id가 2라서 안된다는 답변을 들었는데요.

1)

@BeforeEach에서 매번 테스트마다 id 1L을 새로 정의하고 있는데 auto_increment가 왜 되는걸까요? 그리고 @AfterEach를 통해서 Delete가 되서 다시 id = 1이 넣어질거 같은데 말이죠..

2) 그렇다면 auto_increment를 하면서도 전체테스트가 되려면 어떻게 해야할까요?

0

안녕하세요, 인프런 AI 인턴입니다. HeeSeok Noh님.

동시성 테스트가 부분적으로 실패하는 문제에 대해 도움을 드릴 수 있도록 비슷한 이슈를 다룬 답변을 찾아보았습니다. 두 테스트를 개별적으로 실행하면 문제가 없지만, 전체 테스트 실행 시 오류가 발생하는 상황은 종종 간과되는 동시성 문제나 트랜잭션 관리의 문제일 수 있습니다. 다음은 관련된 몇 가지 주요 원인과 해결책이 담긴 각 질문들입니다:

  1. PESSIMISTIC_WRITE 테스트 시 테스트 클래스 위 @Transactional

    • 출처: 질문에서 @Transactional 어노테이션을 붙이면 첫 스레드풀 사이즈 만큼의 쿼리만 나가고 계속 대기 중인 문제.
    • 설명: 트랜잭션과 락 관리에서 발생할 수 있는 문제로, 모든 테스트가 하나의 트랜잭션에서 실행되어 다른 테스트의 영향을 받는 경우가 있습니다. 이를 해결하려면 테스트에 적절한 트랜잭션 관리가 필요합니다.
  2. 테스트 수행 결과가 항상 에러가 발생합니다.

    • 출처: 여러 스레드를 사용한 동시성 테스트에서 예상된 결과값과 실제 결과값의 불일치 문제.
    • 설명: ExecutorServiceCountDownLatch를 사용하는 경우, 동시성 처리에서 발생할 수 있는 이슈를 다루고 있습니다.
  3. pessimistic lock이 동작하지 않습니다.

    • 출처: Pessimistic Lock 설정 문제와 쿼리 실행의 일관성 이슈.
    • 설명: Pessimistic Lock이 제대로 동작하지 않아서 발생할 수 있는 여러 문제를 설명합니다.

각각의 링크에서 제공된 답변을 통해 문제의 근본 원인과 해결 방안을 파악할 수 있을 것입니다.

이미지 분석에서 NullPointerException이 발생하는 코드 부분을 보면, 트랜잭션 범위 내에서 관리되지 않아서 발생하는 문제일 가능성을 제시하고 있습니다. 예를 들어, @BeforeEach@AfterEach에서 트랜잭션이 제대로 관리되지 않으면, 테스트 데이터가 정확하게 초기화되지 않거나 삭제되지 않을 수 있습니다.

이와 유사한 문제를 겪고 계신 다른 수강생의 질문과 답변을 참고하셔서 문제를 해결하는 데 도움이 되길 바랍니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Hình ảnh hồ sơ của nhs0912
nhs0912

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

Đặt câu hỏi