我已经在下面建立了maven依赖性和配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
@Configuration
@EnableMongoAuditing
public class MongoConfig {
@Bean
MongoTransactionManager transactionManager(MongoDbFactory mongoDbFactory) {
return new MongoTransactionManager(mongoDbFactory);
}
}
Updated:我采用了建议的解决方案,用@Transactional
创建一个bean,并将其注入到我的测试类中。下面是我创建的服务bean:
@Service
@Transactional
@RequiredArgsConstructor
public class MongoTransactionService {
private final UserRepo userRepo;
public void boundToFail() throws RuntimeException {
userRepo.save(User.builder().id("1").build());
throw new RuntimeException();
}
}
和测试类,我在其中注入了MongoTransactionService
的bean:
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class,
includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MongoTransactionService.class))
@ExtendWith(SpringExtension.class)
class MongoTransactionServiceTest {
@Autowired
UserRepo userRepo;
@Autowired
MongoTransactionService mongoTransactionService;
@Test
void testTransactional() {
try {
mongoTransactionService.boundToFail();
} catch (Exception e) {
// do something
}
val user = userRepo.findById("1").orElse(null);
assertThat(user).isNull();
}
}
我期望对boundToFail()
的调用会引发RuntimeException,该调用将回滚已保存的用户,但是该用户在调用后仍会保留在数据库中。
[@Transactional
需要使用单独的Spring bean的public方法,因为通过使用包含与事务基础结构交互的拦截器的代理来包装目标对象来实现事务逻辑,从而实现了事务逻辑。
您的示例遇到两个问题:
测试本身不是Spring bean。即boundToFail(…)
没有添加任何交易行为。 @Transactional
可以用在JUnit测试方法上,但是它控制着测试的事务行为。最显着的是,回滚事务以确保测试中对数据存储所做的更改不会影响其他测试。请参阅参考文档的this section。
即使将事务逻辑应用于boundToFail(…)
,对该方法的本地方法调用也永远不会触发该方法,因为它不会传递正在应用该方法的代理。在the reference documentation中有更多相关信息。
您的问题的解决方案是创建一个单独的带有@Transactional
批注的Spring bean,将其注入到您的测试用例中并从测试中调用该方法。