작성
·
87
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
를 사용하는 경우, 동시성 처리에서 발생할 수 있는 이슈를 다루고 있습니다.각각의 링크에서 제공된 답변을 통해 문제의 근본 원인과 해결 방안을 파악할 수 있을 것입니다.
이미지 분석에서 NullPointerException
이 발생하는 코드 부분을 보면, 트랜잭션 범위 내에서 관리되지 않아서 발생하는 문제일 가능성을 제시하고 있습니다. 예를 들어, @BeforeEach
와 @AfterEach
에서 트랜잭션이 제대로 관리되지 않으면, 테스트 데이터가 정확하게 초기화되지 않거나 삭제되지 않을 수 있습니다.
이와 유사한 문제를 겪고 계신 다른 수강생의 질문과 답변을 참고하셔서 문제를 해결하는 데 도움이 되길 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.