spring启动测试中的事务未回滚

spring启动测试中的事务未回滚,spring,postgresql,spring-boot,junit,spring-jdbc,Spring,Postgresql,Spring Boot,Junit,Spring Jdbc,我的UserController有一个集成测试类。以下课程的内容包括: // imports... @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @RunWith(SpringRunner.class) @Transactional @Rollback public class UserControllerTests { private static final String E

我的
UserController
有一个集成测试类。以下课程的内容包括:

// imports...

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@Transactional
@Rollback
public class UserControllerTests {

    private static final String ENDPOINT = "/v1/users";

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private ApplicationProperties applicationProperties;

    @Test
    public void test_user_create() {
        String token = login("test", "test");
        HttpEntity<UserRequest> request = createRequest(token, "admin", "admin");
        ResponseEntity<User> response = restTemplate.exchange(ENDPOINT, HttpMethod.POST, request, User.class);

        assertEquals(HttpStatus.CREATED, response.getStatusCode());
    }

    private HttpEntity createRequest(String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.set("Authorization", String.format("Bearer %s", token));
        return new HttpEntity(headers);
    }

    private HttpEntity<UserRequest> createRequest(String token, String username, String password) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.set("Authorization", String.format("Bearer %s", token));
        return new HttpEntity<>(new UserRequest(username, password), headers);
    }

    private String login(String username, String password) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.set("Authorization", String.format("Basic %s", Base64.getEncoder().encodeToString(String.format("%s:%s", applicationProperties.getAuth().getClientId(), applicationProperties.getAuth().getClientSecret()).getBytes())));
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "password");
        body.add("username", username);
        body.add("password", password);
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(body, headers);
        ResponseEntity<OAuth2AccessToken> response = restTemplate.exchange("/oauth/token", HttpMethod.POST, request, OAuth2AccessToken.class);
        return response.getBody().getValue();
    }
}
我的应用程序流是
-->
,服务是带有
@Transactional
的注释

我真的被这件事缠住了

找到的一个解决方案对我不起作用,它为测试配置创建了一个
PlatformTransactionManager
bean:

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}
根据官方数据库,当您直接从“web层”应用事务回滚时,不支持事务回滚:

如果您的测试是
@Transactional
,它将在 默认情况下,每个测试方法的结束。但是,由于使用这个, 包含
随机\u端口
隐式定义的\u端口
的排列 提供一个真正的servlet环境,HTTP客户端和服务器将运行 在单独的线程中,因此需要单独的事务。任何交易 在这种情况下,在服务器上启动不会回滚

我建议你考虑以下选项:

  • 在单元测试的情况下,对层和层使用单独的测试

  • 执行集成测试时,在测试方法执行之前创建/恢复表,并在测试方法执行之后删除/清除表。当数据库模式很大时,这种方法可能会有很大的开销,但是您可以根据需要有选择地清除/恢复数据


您在服务层的
@Transactional
方法上是否有
要求\u新的
。这可能是个问题。@mmjmanders您是否将此项目发布在公共回购协议的某个地方,或者您是否可以制作一个单独的示例,重复此错误?@alexsanin我创建了一个示例:是否无法在彼此之间共享事务上下文?
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}