存在这样一个场景: 

    当项目启动时间过长,又没办法缩短的时候,写单元测试就是一个十分耗时的工作,

    这工作不在于使用编写代码,而在于每次run junit test 都需要完整启动一次项目,白白浪费宝贵的生命。

    当由于某个字段没有赋值,或者某个简单判断写错,导致需要再等个3-5分钟启动 junit test,是否会想要执行一次san check?  

  于是乎:

    假若能使用controller来调用test类方法的话,那么在本地调试单元测试时,对于一些简单的代码修改,

    通过热部署,只需要重新进行一次url访问就可执行一个完整的单元测试,

    无需再次启动整个项目。

  正题:

    1. 如何在controller访问src/test ?

    2. 如何编写 ?

  如何在controller访问src/test

    maven项目的默认配置中, src/test目录是测试目录,不会被编译到jar中,也就是在controller调用时会报ClassNotFoundException

    解决办法最好的是在pom文件中修改maven默认的测试目录,将src/test 作为正常目录使用

  1. <build><!-- 将测试目录更改为其他目录 -->
  2. <testSourceDirectory>src/main/test</testSourceDirectory>
  3. </build>

  需要重新maven-update。update后重新将src/test use for building path

  完成后便可以成功启动项目,并可以正常访问。

  如何编写

    可以做一个参考:

controller,最主要内容在于使用controller时,junit的自动回滚可能不会生效,所以手动设置事务,手动触发回滚

  1. @RestController
  2. @RequestMapping(value = "/junit", produces = "application/json;charset=utf-8")
  3. public class TestController {
  4.  
  5. private final Logger logger = LoggerFactory.getLogger(TestController.class);
  6.  
  7. @Autowired
  8. private BizTest bizTest;
  9.  
  10. @GetMapping("test")
    @Transactional(rollbackFor = Exception.class)
  11. public void startJunit() {
  12. bizTest.insertTest();
  13. // 手动开启事务回滚
  14. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  15. }
  16. }

测试类,即可以通过其他类访问,也可以直接执行junit,增加@Componet 或者@Service 还可以通过spring注入方式调用

  1. @Component
  2. public class BizTest extends AbstractTest {
  3.  
  4. @Autowired
  5. private Biz biz;
  6.  
  7. @Test
  8. public void insertTest() {
  9. // 测试业务
  10. }
  11. }

测试抽象父类,用于直接使用junit测试时的配置

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = WebApplication.class)
  3. @Transactional
  4. // @Rollback(false)
  5. public abstract class AbstractTest {
  6.  
  7. protected final Logger logger = LoggerFactory.getLogger(AbstractTest.class);
  8.  
  9. protected void println(Object object) {
  10. System.out.println(object);
  11. }
  12. }

改进: Controller 与Test类解耦

  直接在controller引用Test类,提交代码后容易引起打包错误,这里就需要对两者进行解耦。

  咱的解决办法如下:

     利用spring动态bean注册+类限定名来令两者解耦,并令Test类接受spring容器管理,代码如下:

  1. @GetMapping("test")
  2. @ResponseBody
  3. public String startJunit() {
         // 测试主类限定名
  4. String testImplName = "com.terra.test.JunitTester";
         // 若bean未注册,则注册,SpringConetxtUtil可参考其余地方的Spring动态注册bean
  5. if (SpringContextUtil.getBean(testImplName) == null) {
  6. registerBean(testImplName);
  7. }
  8. try {
  9. IJunitTest junitTester = SpringContextUtil.getBean(testImplName);
  10. junitTester.startTest();
  11. } catch (Exception e) {
  12. if (e.getClass() != UnexpectedRollbackException.class) {
  13. return e.getMessage();
  14. }
  15. }
  16. logger.info("执行单元测试成功");
  17. return "操作成功, 执行完成时间:" + DateUtil.getNowDateTime();
  18. }
  19.   // 注册bean
  20. private void registerBean(String className) {
  21. DefaultListableBeanFactory beanFactory =
  22. (DefaultListableBeanFactory) SpringContextUtil.getApplicationContext().getAutowireCapableBeanFactory();
  23. if (beanFactory.getBean(className) == null) {
  24. BeanDefinition beanDefinition = new GenericBeanDefinition();
  25. beanDefinition.setBeanClassName(className);
  26. beanFactory.registerBeanDefinition(className, beanDefinition);
  27. }
  28. }
  29.   // 单元测试主类接口
  30. public static interface IJunitTest {
  31. void startTest();
  32. }

测试主类代码:

  1. @Component
  2. public class JunitTester extends AbstractTest implements IJunitTest {
  3.  
  4. @Autowired
  5. private BizTest1 bizTest1;
  6. @Autowired
  7. private BizTest2 bizTest2;
  8.  
  9. @Transactional(rollbackFor = Exception.class)
  10. @Override
  11. public void startTest() {
  12. // 手动开启事务回滚
  13. bizTest1.before();
  14. bizTest1.test();
  15. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  16. }
  17. }

这样做的好处是,环境上的代码没有src/test也不会报错,而本地只需要进行注释和去除注释@RequestMapping,便无需要再修改controller代码

所有单元测试代码操作便可在测试主类及其测试类中进行,可喜可贺。

【maven】【spring boot】【单元测试】 使用controller 执行单元测试类的更多相关文章

  1. Spring Boot Web 开发@Controller @RestController 使用教程

    在 Spring Boot 中,@Controller 注解是专门用于处理 Http 请求处理的,是以 MVC 为核心的设计思想的控制层.@RestController 则是 @Controller ...

  2. Spring Boot(十二)单元测试JUnit

    一.介绍 JUnit是一款优秀的开源Java单元测试框架,也是目前使用率最高最流行的测试框架,开发工具Eclipse和IDEA对JUnit都有很好的支持,JUnit主要用于白盒测试和回归测试. 白盒测 ...

  3. 如何对Spring MVC中的Controller进行单元测试

    对Controller进行单元测试是Spring框架原生就支持的能力,它可以模拟HTTP客户端发起对服务地址的请求,可以不用借助于诸如Postman这样的外部工具就能完成对接口的测试. 具体来讲,是由 ...

  4. Spring Boot 系列(二)单元测试&网络请求

    实际开发中,Junit单元测试是必不可少的.在spring-boot 中可以通过测试模块(spring-boot-starter-test)快速使用单元测试功能. 开始 本示例在 spring boo ...

  5. Spring boot 项目导出可执行jar

    配置文件中添加插件 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>s ...

  6. Eclipse完成Maven + Spring Boot + Mybatis + jsp

    Spring Boot 完成WEB项目开发 开发工具:eclipse 框架:Maven:Spring Boot:Mybatis 界面:jsp:javascript:css 前言: 在SpringBoo ...

  7. 将 Spring boot 项目打成可执行Jar包,及相关注意事项(main-class、缺少 xsd、重复打包依赖)

    最近在看 spring boot 的东西,觉得很方便,很好用.对于一个简单的REST服务,都不要自己部署Tomcat了,直接在 IDE 里 run 一个包含 main 函数的主类就可以了. 但是,转念 ...

  8. spring boot mybatis 打成可执行jar包后启动UnsatisfiedDependencyException异常

    我的spring boot + mybatis项目在idea里面执行正常,但发布测试环境打成可执行jar包后就启动失败,提示错误如下: [ ERROR] [2018-08-30 17:23:48] o ...

  9. Spring boot进阶-配置Controller、interceptor...

    1.配置SpringBootApplication(对spring boot来说这是最基本) package io.github.syske.springboot31; import org.spri ...

随机推荐

  1. Myatis中的OGNL和bind标签的结合用法

    1.MyBatis常用的OGNL e1 or e2 e1 and e2 e1 == e2,e1 eq e2 e1 != e2,e1 neq e2 e1 lt e2:小于 e1 lte e2:小于等于, ...

  2. MediaAPIController

    using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.D ...

  3. Linux与Windows的设备驱动模型对比

    Linux与Windows的设备驱动模型对比 名词缩写: API 应用程序接口(Application Program Interface ) ABI 应用系统二进制接口(Application Bi ...

  4. 配置UOJ数据的正确姿势

    最近瞎搞用开源UOJ搭了个OJ,在题目配置方面搞了挺久,一开始看vfleaking的文档还折腾了SVN,特意写下这篇文章为后来人少走弯路 Step 1 拥有管理权限并设置好题面,支持\(LaTex\) ...

  5. 【Android】笔记

    一.环境搭建 1.  下载JDK, JRE , 设置JDK 和 JRE环境变量 , PATH C:\jdk1.6.0_15\bin; JAVA_HOME C:\jdk1.6.0_15 重启电脑,    ...

  6. vue项目中引入animate.css和wow.js

    本文转自:https://blog.csdn.net/liyunkun888/article/details/85003152 https://www.zhuimengzhu.com/content/ ...

  7. vue使用sass报Modele build failed: TypeError: this.getResolve is not a function at Object.loader...

    项目中使用sass报错,之前一直使用同样的安装方式 cnpm install sass-loader node-sass -D,正常使用没问题,没想到这次同样的方式却报错了,网上查的原因是sass-l ...

  8. C#【堆与栈 值类型 引用类型】

    先说C#中值类型和引用类型 概念: 1.值类型:数据存储在内存的堆栈中,从堆栈中可以快速地访问这些数据,因此,值类型表示实际的数据. 2.引用类型:表示指向存储在内存堆中的数据的指针或引用(包括类.接 ...

  9. db2 with用法

    最近在研究db2 递归查询时想到了with,一直以为with只是用来查询递归,但是实际with功能强大,还有更加强大的功能,偶然读到一位大神的文章,对with做了很详细的解读,特贴出来供大家学习研究 ...

  10. Mac下使用Charles抓包https接口

    1 官方网站下载,安装好Charles https://www.charlesproxy.com/download/ 2 安装ssl证书 3 信任证书 4 手机iPhone配置 ,获取证书url 5 ...