Skip to content

[건의사항] MongoDB Transaction 기능 테스트 환경 구성 #216

@doma17

Description

@doma17

문제점

TransactionManager 부재가 MongoDB를 Main DB로 사용하는데에 문제점인 것 같습니다.
Spring Boot는 MongoDB용 TransactionManager를 자동으로 설정하지 않습니다.
JPA와 달리 MongoDB 트랜잭션은 추가 설정이 필요하고.

또한, MongoDB Replica Set 또는 Sharded Cluster 환경에서만 가능하다고 합니다.
따라서 아래의 방법을 도입하기 전에 MongoDB 설정을 변경할 필요가 있습니다.

Reference

https://oliveyoung.tech/2024-12-17/catalog-mongo-transaction-2/

테스트 롤백 불가

@Transactional이 작동하지 않으면 테스트 후 데이터가 자동으로 롤백되지 않아 테스트 간 데이터 오염이 발생할 것입니다.

해결 방법

1. MongoTransactionManager 설정

테스트 설정 클래스

@TestConfiguration
public class MongoTestConfig {
    
    @Bean
    @Primary
    public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }
}

테스트 클래스에서 사용

@DataMongoTest
@Import(MongoTestConfig.class)
@Transactional
class ItemRepositoryTest {
    
    @Autowired
    private ItemRepository itemRepository;
    
    @Test
    void shouldSaveAndFindItem() {
        Item item = new Item("001", "Test Item");
        itemRepository.save(item);
        
        Optional<Item> found = itemRepository.findById("001");
        assertThat(found).isPresent();
    }
}

2. 수동 데이터 정리 방식 - @BeforeEach/@AfterEach 활용

@DataMongoTest
class ItemRepositoryTest {
    
    @Autowired
    private ItemRepository itemRepository;
    
    @AfterEach
    void cleanup() {
        itemRepository.deleteAll();
    }
    
    @Test
    void shouldSaveAndFindItem() {
        // 테스트 로직
    }
}

3. @DirtiesContext 사용 - 컨텍스트 재생성 방식

@DataMongoTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class ItemRepositoryTest {
    // 각 테스트 후 Spring 컨텍스트 재생성
}

4. TestContainers 활용 - 실제 MongoDB 환경

@SpringBootTest
@Testcontainers
class ItemRepositoryIntegrationTest {
    
    @Container
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4.4")
            .withReplicaSet();
    
    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
    }
    
    @Transactional
    @Test
    void shouldWorkWithTransactions() {
        // 실제 Replica Set 환경에서 트랜잭션 테스트
    }
}

권장 접근법

개발 단계별 전략

  1. 단위 테스트: 수동 데이터 정리 방식 사용
  2. 통합 테스트: MongoTransactionManager 설정 또는 TestContainers 활용
  3. 성능 테스트: 실제 MongoDB Replica Set 환경 구성

실용적 해결책

@DataMongoTest
class ItemRepositoryTest {
    
    @Autowired
    private TestEntityManager entityManager; // MongoDB에는 없음
    
    @Autowired
    private MongoTemplate mongoTemplate;
    
    @BeforeEach
    void setup() {
        mongoTemplate.getCollection("items").deleteMany(new Document());
    }
    
    @Test
    void shouldSaveItem() {
        // 테스트 로직
    }
}

초기에는 수동 정리 방식으로 추가하고, 필요에 따라 트랜잭션 설정을 추가하는 것이 실용적일 것 같습니다.

Metadata

Metadata

Assignees

Labels

⚙ Setting개발 환경 세팅📃 Docs문서 작성 및 수정 (README.md 등)

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions