인프런 커뮤니티 질문&답변
Pessimistic Lock 전체 테스트 오류 문의
작성
·
299
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);
}
}

이런 오류가 나는데 @BeforeEach에서 새로 등록하고
@AfterEach에서 delete를 해줘서 각각의 테스트에 영향이 없을거 같은데 왜 나는지 잘 모르겠어요 ㅠ
github : https://github.com/nhs0912/stock
답변 3
0
HeeSeok Noh 님 안녕하세요.
1) 데이터베이스의 설정이 auto_increment 로 되어있기때문에 그럴겁니다.
2) 테스트를 시작하기전에 findByFirst 를 하여 id 를 얻어온 후 그 값을 사용하면 될것같습니다.
감사합니다.
0
질문 검색 해보니 다른 답변에서 테스트를 2개 돌리면 Auto_increment 때문에 두번째 테스트에서 id가 2라서 안된다는 답변을 들었는데요.
1)
@BeforeEach에서 매번 테스트마다 id 1L을 새로 정의하고 있는데 auto_increment가 왜 되는걸까요? 그리고 @AfterEach를 통해서 Delete가 되서 다시 id = 1이 넣어질거 같은데 말이죠..
2) 그렇다면 auto_increment를 하면서도 전체테스트가 되려면 어떻게 해야할까요?
0
안녕하세요, 인프런 AI 인턴입니다. HeeSeok Noh님.
동시성 테스트가 부분적으로 실패하는 문제에 대해 도움을 드릴 수 있도록 비슷한 이슈를 다룬 답변을 찾아보았습니다. 두 테스트를 개별적으로 실행하면 문제가 없지만, 전체 테스트 실행 시 오류가 발생하는 상황은 종종 간과되는 동시성 문제나 트랜잭션 관리의 문제일 수 있습니다. 다음은 관련된 몇 가지 주요 원인과 해결책이 담긴 각 질문들입니다:
PESSIMISTIC_WRITE 테스트 시 테스트 클래스 위 @Transactional
- 출처: 질문에서
@Transactional어노테이션을 붙이면 첫 스레드풀 사이즈 만큼의 쿼리만 나가고 계속 대기 중인 문제.
- 설명: 트랜잭션과 락 관리에서 발생할 수 있는 문제로, 모든 테스트가 하나의 트랜잭션에서 실행되어 다른 테스트의 영향을 받는 경우가 있습니다. 이를 해결하려면 테스트에 적절한 트랜잭션 관리가 필요합니다.
- 출처: 질문에서
-
- 출처: 여러 스레드를 사용한 동시성 테스트에서 예상된 결과값과 실제 결과값의 불일치 문제.
- 설명:
ExecutorService와CountDownLatch를 사용하는 경우, 동시성 처리에서 발생할 수 있는 이슈를 다루고 있습니다.
- 출처: 여러 스레드를 사용한 동시성 테스트에서 예상된 결과값과 실제 결과값의 불일치 문제.
-
- 출처: Pessimistic Lock 설정 문제와 쿼리 실행의 일관성 이슈.
- 설명: Pessimistic Lock이 제대로 동작하지 않아서 발생할 수 있는 여러 문제를 설명합니다.
- 출처: Pessimistic Lock 설정 문제와 쿼리 실행의 일관성 이슈.
각각의 링크에서 제공된 답변을 통해 문제의 근본 원인과 해결 방안을 파악할 수 있을 것입니다.
이미지 분석에서 NullPointerException이 발생하는 코드 부분을 보면, 트랜잭션 범위 내에서 관리되지 않아서 발생하는 문제일 가능성을 제시하고 있습니다. 예를 들어, @BeforeEach와 @AfterEach에서 트랜잭션이 제대로 관리되지 않으면, 테스트 데이터가 정확하게 초기화되지 않거나 삭제되지 않을 수 있습니다.
이와 유사한 문제를 겪고 계신 다른 수강생의 질문과 답변을 참고하셔서 문제를 해결하는 데 도움이 되길 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





