다중 스레드 테스트

JUNO LIM·2023년 5월 17일

Spring

목록 보기
8/9

사용자가 포스트에 좋아요를 누르는 기능이 있는데 여러 사용자가 동시에 한 포스트에 좋아요 요청 시 동시성 문제가 발생되는지 보기 위해 테스트를 작성해 보았다.

SimultaneityTest

@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 쿼리를 실행한다.

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

profile
개발개발개발자

0개의 댓글