Spring集成测试不会回滚

时间:2014-05-15 11:03:11

标签: spring-mvc testing transactions integration-testing rollback

我已经通过q& a围绕这个问题做了一些研究。很多问题似乎都在解决,但不是真的。

所以这就是事情:

  • 我收到CaseController,代理CaseService,代理人转而CaseRepository

  • 我在@Transactional

  • 上的每个方法上都CaseServiceImpl
  • 我收到CaseControllerIntegrationTest,我从CaseController执行RESTful请求并测试完整周期。

问题是 - 我的交易没有回滚。

其中一项测试是

@Test 
public void verifyDeleteSuccessfulOnExistingCase() {

        final String urlWithPlaceholders = serverPrefix + RequestMappings.CASES_RESOURCE_MAPPING + "/{caseId}";

        final ResponseEntity<CaseResource> response =
                restTemplate.exchange(
                        urlWithPlaceholders,
                        HttpMethod.DELETE,
                        null,
                        CaseResource.class, existingWsId_1, caseId);

        assertThat(response, notNullValue());
        assertThat(response.getBody(), nullValue());
        assertThat(response.getStatusCode(), is(HttpStatus.NO_CONTENT));
        assertThat(caseRepository.exists(caseId), is(false));

}

在这个测试中,我删除了一个在启动时为我插入的案例,感谢hibernate和import.sql

测试成功,问题是我想在接下来的测试中继续解决这种情况,但事务似乎没有回滚,并且案例被永久删除,不能用于下一次测试。

  • 我尝试将@TransactionalCaseServiceImpl移到CaseController,但它没有任何区别。

  • 我可以说我的下方杆CaseRepositoryTest在每次测试后都成功执行了回滚。

CaseControllerIntegrationTest之上我得到了:

@ActiveProfiles("integration-test")
@Transactional
@TransactionConfiguration
@IntegrationTest
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = AppConfiguration.class)
public class CaseControllerIntegrationTest {
...

AppConfiguration看起来像这样:

@Configuration
@EnableAutoConfiguration
@ComponentScan
@EnableTransactionManagement
public class AppConfiguration {
}

我正在使用的数据库是 hsqldb

最后一条重要信息 - 日志实际上表明回滚已完成:

  

2014-05-15 07:54:44.391 TRACE -   o.s.t.c.t.TransactionalTestExecutionListener - 结束交易   测试上下文[DefaultTestContext @ 2eb0cefe testClass =   CaseControllerIntegrationTest,testInstance =   om.services.casemanagement.web.CaseControllerIntegrationTest@5a2ae1ab,    testMethod = verifyDeleteSuccessfulOnExistingCase @CaseControllerIntegrationTest,   testException = [null],mergedContextConfiguration =   [WebMergedContextConfiguration @ 2bec068b testClass =   CaseControllerIntegrationTest,locations ='{}',classes ='{class   om.services.AppConfiguration}',contextInitializerClasses ='[]',   activeProfiles ='{integration-test}',resourceBasePath =   'src / main / webapp',contextLoader =   'org.springframework.boot.test.SpringApplicationContextLoader',父   = [null]]];交易状态[org.springframework.transaction.support.DefaultTransactionStatus@3869a6e5];   rollback [true]

     

2014-05-15 07:54:44.403 INFO -   o.s.t.c.t.TransactionalTestExecutionListener - 回滚事务   测试执行测试上下文后[DefaultTestContext @ 2eb0cefe   testClass = CaseControllerIntegrationTest,testInstance =   om.services.casemanagement.web.CaseControllerIntegrationTest@5a2ae1ab,    testMethod = verifyDeleteSuccessfulOnExistingCase @CaseControllerIntegrationTest,   testException = [null],mergedContextConfiguration =   [WebMergedContextConfiguration @ 2bec068b testClass =   CaseControllerIntegrationTest,locations ='{}',classes ='{class   om.services.AppConfiguration}',contextInitializerClasses ='[]',   activeProfiles ='{integration-test}',resourceBasePath =   'src / main / webapp',contextLoader =   'org.springframework.boot.test.SpringApplicationContextLoader',父   = [null]]]

我正在使用Spring 4.0.3发行版。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

看看你在这里做了什么:

您从 thread1 发送http请求,该请求由Web容器的 thread2 捕获并处理。前者无法控制后者管理的交易。

如果您持有CaseController实例并直接从测试方法对其方法进行显式调用,您将享受@Transactional为您提供的自动回滚功能。

答案 1 :(得分:2)

尽管@kumetix提到了它,但对此的正确答案是,无法在测试方法中回滚通过RestTemplate发出的请求触发的事务

您唯一的选择是通过手动删除来回滚交易。

请参阅此link with similiar question以获取其他意见。

希望有所帮助。

答案 2 :(得分:0)

这种方式适合我。

步骤1:创建一个私有CaseService并在其上添加@Autowired。还要添加一个私有的MockMvc变量。

private MockMvc restCaseController;

@Autowired
private CaseService caseService; 

步骤2:创建一个设置方法并使用@Before。

进行注释
@Before
private void setup() {
  MockitoAnnotations.initMocks(this);
  CaseController casecontroller = new CaseController(caseService);
  this.restCaseController = 
  MockMvcBuilders.standaloneSetup(casecontroller).build();
}

第3步:创建测试方法,使用@Test和@Transactional注释它。

@Test
@Transactional
public void testMethod() {
    restCaseController.perform(post("/api/post")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(jsonObject))
                      .andExpect(status().isCreated());
}

这种方式对我有用,我能够在没有任何回滚问题的情况下得到响应。