사용자가 포스트에 좋아요를 누르는 기능이 있는데 여러 사용자가 동시에 한 포스트에 좋아요 요청 시 동시성 문제가 발생되는지 보기 위해 테스트를 작성해 보았다.
@DisplayName("동시성 문제 테스트")
@SpringBootTest
class SimultaneityTest {
private final PostRepository postRepository;
private final UserAccountRepository userAccountRepository;
private final LikesRepository likesRepository;
public SimultaneityTest(
@Autowired PostRepository postRepository,
@Autowired UserAccountRepository userAccountRepository,
@Autowired LikesRepository likesRepository,
) {
this.postRepository = postRepository;
this.userAccountRepository = userAccountRepository;
this.likesRepository = likesRepository;
}
@BeforeEach
public void init() {
for (int i = 1; i <= 200; i++) {
UserAccount userAccount = createUserAccount("juno" + i);
userAccountRepository.save(userAccount);
}
}
@AfterEach
void rollback() {
likesRepository.deleteAll();
postRepository.deleteAll();
userAccountRepository.deleteAll();
}
@DisplayName("like 등록 시 동시성 테스트")
@Test
void likePostSimultaneityTest() throws InterruptedException {
long postId = 1L;
int numThread = 200;
CountDownLatch latch = new CountDownLatch(numThread);
Post post = postRepository.getReferenceById(postId);
for (int i = 1; i <= numThread; i++) {
UserAccount userAccount = userAccountRepository.getReferenceById("juno" + i);
Runnable runnable = () -> {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(status -> {
try {
Likes likes = Likes.of(userAccount, post);
likesRepository.save(likes);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
latch.countDown();
}
return null;
});
};
Thread thread = new Thread(runnable);
thread.start();
}
latch.await();
List<Likes> likes = likesRepository.findAllByPost_Id(postId);
assertThat(likes).hasSize(numThread);
}
private UserAccount createUserAccount(String username) {
return UserAccount.of(username, "password", username + "@mail.com");
}
}
테스트에서도 생성자를 사용한 의존성 주입이 가능하다.
@BeforeEach와 @AfterEach를 사용해서 유저를 초기화하고 테스트가 끝난 후에는 모두 삭제한다.
200명의 사용자가 한 포스트에 동시에 좋아요를 누르는 상황을 테스트하기 위해 200개의 스레드를 생성해서 병렬로 Likes 테이블에 insert 쿼리를 실행한다.

이번 테스트에서는 동시성 문제가 발생하지 않았는데 다른 로직도 동시성 테스트를 만들어서 적용해볼 예정이다