0


单元测试JunitTest加@Transactional事务自动回滚

问题

在测试事务传播行为的时候,使用单位测试加了@Transactional,一开始是正常,后面出现了异常,即使没有报错的情况下,事务也会自动回滚

代码

@RunWith(SpringRunner.class)@SpringBootTestpublicclassTranTest{@AutowiredprivateKsAService ksAService;@AutowiredprivateKsBService ksBService;@Test@Transactionalpublicvoidtest(){KsA ksA =newKsA();
        ksA.setName("林");
        ksAService.insert(ksA);KsB ksB =newKsB();
        ksB.setAge(10);
        ksBService.insert(ksB);}}

异常

2022-10-20 11:27:31.818 [TID: N/A][main] INFO  o.s.t.c.t.TransactionContext -Began transaction (1)fortest context [DefaultTestContext@c430e6c testClass = TranTest, testInstance = com.forlan.kaoshi.TranTest@ce0c2b3, testMethod = test@TranTest, testException =[null], mergedContextConfiguration =[WebMergedContextConfiguration@312aa7c testClass = TranTest, locations ='{}', classes ='{class com.forlan.kaoshi.KaoshiApplication}', contextInitializerClasses ='[]', activeProfiles ='{}', propertySourceLocations ='{}', propertySourceProperties ='{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@418e7838, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3e2e18f2, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@48ae9b55, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@72f926e6, org.spockframework.spring.mock.SpockContextCustomizer@0], resourceBasePath ='src/main/webapp', contextLoader ='org.springframework.boot.test.context.SpringBootContextLoader', parent =[null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@1e1b512e]; rollback [true]2022-10-20 11:27:32.296 [TID: N/A][main] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsAMapper.insert->【系统调用】sql : insert into ks_a(name) values ('林')2022-10-20 11:27:32.298 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==>  Preparing: insert into ks_a(name) values (?)2022-10-20 11:27:32.316 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==> Parameters: 林(String)2022-10-20 11:27:32.365 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -<==    Updates: 12022-10-20 11:27:32.377 [TID: N/A][main] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsBDao.insert->【系统调用】sql : insert into ks_b(age) values (10)2022-10-20 11:27:32.377 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==>  Preparing: insert into ks_b(age) values (?)2022-10-20 11:27:32.377 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==> Parameters: 10(Integer)2022-10-20 11:27:32.421 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -<==    Updates: 12022-10-20 11:27:32.470 [TID: N/A][main] INFO  o.s.t.c.t.TransactionContext -Rolled back transaction for test: [DefaultTestContext@c430e6c testClass = TranTest, testInstance = com.forlan.kaoshi.TranTest@ce0c2b3, testMethod = test@TranTest, testException =[null], mergedContextConfiguration =[WebMergedContextConfiguration@312aa7c testClass = TranTest, locations ='{}', classes ='{class com.forlan.kaoshi.KaoshiApplication}', contextInitializerClasses ='[]', activeProfiles ='{}', propertySourceLocations ='{}', propertySourceProperties ='{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@418e7838, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3e2e18f2, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@48ae9b55, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@72f926e6, org.spockframework.spring.mock.SpockContextCustomizer@0], resourceBasePath ='src/main/webapp', contextLoader ='org.springframework.boot.test.context.SpringBootContextLoader', parent =[null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]

Rolled back transaction for test,数据都回滚了
在这里插入图片描述
在这里插入图片描述

解决

1、方法加注解@Rollback(false)

该注解是直接关闭了自动回滚,异常情况下,数据也不会回滚

@Test@Transactional@Rollback(false)publicvoidtest(){......}
2022-10-20 11:24:36.132 [TID: N/A][main] INFO  o.s.t.c.t.TransactionContext -Began transaction (1)fortest context [DefaultTestContext@66982506 testClass = TranTest, testInstance = com.forlan.kaoshi.TranTest@5efa2b92, testMethod = test@TranTest, testException =[null], mergedContextConfiguration =[WebMergedContextConfiguration@70cf32e3 testClass = TranTest, locations ='{}', classes ='{class com.forlan.kaoshi.KaoshiApplication}', contextInitializerClasses ='[]', activeProfiles ='{}', propertySourceLocations ='{}', propertySourceProperties ='{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3e2e18f2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3e92efc3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@30ee2816, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@27ce24aa, org.spockframework.spring.mock.SpockContextCustomizer@0], resourceBasePath ='src/main/webapp', contextLoader ='org.springframework.boot.test.context.SpringBootContextLoader', parent =[null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@1838e02]; rollback [false]2022-10-20 11:24:38.073 [TID: N/A][main] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsAMapper.insert->【系统调用】sql : insert into ks_a(name) values ('林')2022-10-20 11:24:38.077 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==>  Preparing: insert into ks_a(name) values (?)2022-10-20 11:24:38.113 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==> Parameters: 林(String)2022-10-20 11:24:38.134 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -<==    Updates: 12022-10-20 11:24:38.249 [TID: N/A][main] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsBDao.insert->【系统调用】sql : insert into ks_b(age) values (10)2022-10-20 11:24:38.249 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==>  Preparing: insert into ks_b(age) values (?)2022-10-20 11:24:38.249 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==> Parameters: 10(Integer)2022-10-20 11:24:38.267 [TID: N/A][main] DEBUG c.m.k.forlan.mapper.KsBDao.insert -<==    Updates: 12022-10-20 11:24:38.323 [TID: N/A][main] INFO  o.s.t.c.t.TransactionContext -Committed transaction for test: [DefaultTestContext@66982506 testClass = TranTest, testInstance = com.forlan.kaoshi.TranTest@5efa2b92, testMethod = test@TranTest, testException =[null], mergedContextConfiguration =[WebMergedContextConfiguration@70cf32e3 testClass = TranTest, locations ='{}', classes ='{class com.forlan.kaoshi.KaoshiApplication}', contextInitializerClasses ='[]', activeProfiles ='{}', propertySourceLocations ='{}', propertySourceProperties ='{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@3e2e18f2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3e92efc3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@30ee2816, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@27ce24aa, org.spockframework.spring.mock.SpockContextCustomizer@0], resourceBasePath ='src/main/webapp', contextLoader ='org.springframework.boot.test.context.SpringBootContextLoader', parent =[null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]

数据成功入库
在这里插入图片描述
在这里插入图片描述

2、使用http访问

通过TestRestTemplate 访问controller方法

@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.DEFINED_PORT)publicclassTranTest{@Testpublicvoidadd()throwsException{TestRestTemplate restTemplate =newTestRestTemplate();
        restTemplate.postForLocation("http://localhost:8100/kaoshi/forlan/test/add",KsA.class);}}@RestController@RequestMapping("/forlan/test")publicclassTestController{@AutowiredprivateKsAService ksAService;@AutowiredprivateKsBService ksBService;@PostMapping("/add")@Transactionalpublicvoidadd(){KsA ksA =newKsA();
        ksA.setName("林");
        ksAService.insert(ksA);KsB ksB =newKsB();
        ksB.setAge(10);
        ksBService.insert(ksB);}}
2022-10-27 16:10:46.053 [TID: N/A][http-nio-8100-exec-1] INFO  o.a.c.c.C.[.[localhost].[/forlan] -Initializing Spring DispatcherServlet 'dispatcherServlet'2022-10-27 16:10:46.053 [TID: N/A][http-nio-8100-exec-1] INFO  o.s.web.servlet.DispatcherServlet -Initializing Servlet 'dispatcherServlet'2022-10-27 16:10:46.158 [TID: N/A][http-nio-8100-exec-1] INFO  o.s.web.servlet.DispatcherServlet -Completed initialization in105 ms
2022-10-27 16:10:46.211 [TID: N/A][http-nio-8100-exec-1] INFO  c.m.k.common.config.ControllerAspect -request(2666eff88910474a8f0a921c5da76454)【请求方法TestController.add1(),参数:[]】 end 
2022-10-27 16:10:46.227 [TID: N/A][http-nio-8100-exec-1] INFO  com.zaxxer.hikari.HikariDataSource -DatebookHikariCP - Starting...
2022-10-27 16:10:46.519 [TID: N/A][http-nio-8100-exec-1] INFO  com.zaxxer.hikari.HikariDataSource -DatebookHikariCP - Start completed.
2022-10-27 16:10:46.577 [TID: N/A][http-nio-8100-exec-1] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsAMapper.insert->租户【系统调用】sql : insert into ks_a(name) values ('林')2022-10-27 16:10:46.580 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==>  Preparing: insert into ks_a(name) values (?)2022-10-27 16:10:46.601 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -==> Parameters: 林(String)2022-10-27 16:10:46.615 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsAMapper.insert -<==    Updates: 12022-10-27 16:10:46.627 [TID: N/A][http-nio-8100-exec-1] INFO  c.m.interceptor.TenancyInterceptor -TenancyInterceptor插入日志信息->KsBDao.insert->租户【系统调用】sql : insert into ks_b(age) values (10)2022-10-27 16:10:46.627 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==>  Preparing: insert into ks_b(age) values (?)2022-10-27 16:10:46.628 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsBDao.insert -==> Parameters: 10(Integer)2022-10-27 16:10:46.643 [TID: N/A][http-nio-8100-exec-1] DEBUG c.m.k.forlan.mapper.KsBDao.insert -<==    Updates: 12022-10-27 16:10:46.670 [TID: N/A][http-nio-8100-exec-1] INFO  c.m.k.common.config.ControllerAspect -request(2666eff88910474a8f0a921c5da76454)end, cost 459ms

数据成功入库
在这里插入图片描述
在这里插入图片描述

注意:@SpringBootTest需要加上参数(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT),不然会出现下面错误

org.springframework.web.client.ResourceAccessException: I/O error on POST request for"http://localhost:8100/kaoshi/forlan/test/add": Connect to localhost:8100 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect; nested exception is org.apache.http.conn.HttpHostConnectException: Connect to localhost:8100 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect

原理

官方文档说明

官方文档说明地址
43.3 Testing Spring Boot applications

@SpringBootTest属性webEnvironment

  • Mock(默认) : 加载WebApplicationContext 并提供模拟的web环境 Servlet环境,使用此批注时,不会启动嵌入式服务器
  • RANDOM_PORT : 加载WebServerApplicationContext 并提供真实的web环境,嵌入式服务器, 监听端口是随机的
  • DEFINED_PORT : 加载WebServerApplicationContext并提供真实的Web环境,嵌入式服务器启动并监听定义的端口(来自 application.properties或默认端口 8080)
  • NONE : 使用SpringApplication加载ApplicationContext 但不提供任何Web环境

If your test is , it will rollback the transaction at the end of each test method by default. If you’re using this arrangement in combination with either or , any transaction initiated on the server won’t rollback as the test is running in a different thread than the server processing.@Transactional RANDOM_PORT DEFINED_PORT

大概意思就是,在单元测试中,加了@Transactional注解,默认情况下,它将在每个测试方法结束时回滚事务。当我们使用RANDOM_PORT或DEFINED_PORT任一作为运行环境,服务器上启动的任何事务都不会回滚,因为测试运行在不同线程中。


本文转载自: https://blog.csdn.net/qq_36433289/article/details/127392612
版权归原作者 程序员Forlan 所有, 如有侵权,请联系我们删除。

“单元测试JunitTest加@Transactional事务自动回滚”的评论:

还没有评论