网易首页 > 网易号 > 正文 申请入驻

IDEA懒人必备插件,自动生成单元测试,太爽了!

0
分享至

今天来介绍一款工具Squaretest,它是一款自动生成单元测试的插件,为什么会用到它?

主要因为最近公司上了代码质量管控的指标,会考评各个项目的单元测试覆盖率,以及sonar扫描出来的各种问题,很多老项目老代码,或者着急交付的项目,单元测试严重缺失,覆盖率只有5%不到。

所以几个小伙伴这几天就在疯狂的堆单元测试,3个人堆了2天才堆到30%,于是我也来上手帮忙写了两个,写到第二个的时候就发现,这个活不应该是人干的,要去看原来的代码,然后根据逻辑写各种Mock,感觉是有迹可循的东西,所以就查了下,发现果然有插件帮我们来干这个事情,那么解下来就来看看。

我使用的是idea,我们先来下载一下插件,File——>Settings——>Plugins,搜索Squaretest,然后install就好了,插件安装完成后需要重启一下

重启之后,菜单栏就多了一项Squaretest,下面我们来讲下怎么用,大家也可以通过看这个菜单的最后一项:Generate Test Methods(Help)来看它的一个演示,但演示不太全,我下面截图给大家看下我怎么用的,以及一些使用心得。

首先我们打开一个类,这个类就是我们即将要作为实验的类,这个类有7个public方法,因为Squaretest生成的单元测试方法都是只能生成public的,当然这也是合理的嘛!毕竟private的肯定被public调用了。

如果我们来手写这个类的,光看都要一会,下面看我操作,打开你的类,光标定位到代码里,右击鼠标选择Generate…

然后你就会看到这里有两个熟悉的图标,第一次的话选择第二个选项,它会让你选择你一下单元测试的模板,因为我已经选择过了,所以我现在演示不回再弹出,但后面我会告诉你怎么更改模板。

选择第二项后就会弹出一个框看下面这里它自动会识别出当前类需要Mock的成员变量,直接点ok

自动会使用类的真实目录层次在test文件夹中创建出来一个单元测试类,类名就是原类名后加Test

我把代码贴出来给大家看看它生成出来的是什么样的,看看吓不吓人,牛逼牛逼,7个单元测试方法,秒秒钟就出来了,各位看官你们自己写要多久能写出来,毕竟时间就是金钱啊!然后我们执行一把试试!

public class CrawlerScreenShotServiceImplTest {

@Mock
private CrawerScreenShotTaskMapper mockCrawerScreenShotTaskMapper;
@Mock
private CrawerScreenShotTaskLogMapper mockCrawerScreenShotTaskLogMapper;

@InjectMocks
private CrawlerScreenShotServiceImpl crawlerScreenShotServiceImplUnderTest;

@Before
public void setUp() {
initMocks(this);
}

@Test
public void testReceiveData() {
// Setup
final CrawlerScreenShotVO vo = new CrawlerScreenShotVO();
vo.setUrl("url");
vo.setPcFlag(false);
vo.setMembergroup("membergroup");
vo.setTaskType(0);
vo.setUrlType(0);

when(mockCrawerScreenShotTaskLogMapper.saveSelective(any(CrawerScreenShotTaskLog.class))).thenReturn(0);
when(mockCrawerScreenShotTaskMapper.saveBatch(Arrays.asList(new CrawlerScreenShotTask(0L, "url", "imageOssUrl", false, false, "memberGroup", 0, 0, "fileName", new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), false, "skuCode", "state", "operater")))).thenReturn(0);

// Run the test
final Result result = crawlerScreenShotServiceImplUnderTest.receiveData(vo);

// Verify the results
}

@Test
public void testListJobScreenShotTask() {
// Setup

// Configure CrawerScreenShotTaskMapper.listJobScreenShotTask(...).
final CrawlerScreenShotTaskDto crawlerScreenShotTaskDto = new CrawlerScreenShotTaskDto();
crawlerScreenShotTaskDto.setId(0L);
crawlerScreenShotTaskDto.setUrl("url");
crawlerScreenShotTaskDto.setSkuCode("skuCode");
crawlerScreenShotTaskDto.setPcFlag(false);
crawlerScreenShotTaskDto.setMemberGroup("memberGroup");
crawlerScreenShotTaskDto.setUrlType(0);
crawlerScreenShotTaskDto.setFileName("fileName");
crawlerScreenShotTaskDto.setTaskType(0);
crawlerScreenShotTaskDto.setState("state");
final List crawlerScreenShotTaskDtos = Arrays.asList(crawlerScreenShotTaskDto);
when(mockCrawerScreenShotTaskMapper.listJobScreenShotTask(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(crawlerScreenShotTaskDtos);

// Run the test
final List result = crawlerScreenShotServiceImplUnderTest.listJobScreenShotTask();

// Verify the results
}

@Test
public void testQuery() {
// Setup
final NikeScreenShotListRequestVo requestVo = new NikeScreenShotListRequestVo();
requestVo.setUrl("url");
requestVo.setUrlType(0);
requestVo.setStartTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
requestVo.setEndTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
requestVo.setStatus(0);
requestVo.setPcFlag(0);
requestVo.setPageNum(0);
requestVo.setPageSize(0);

// Configure CrawerScreenShotTaskMapper.query(...).
final PimScreenShotVo pimScreenShotVo = new PimScreenShotVo();
pimScreenShotVo.setId(0L);
pimScreenShotVo.setUrl("url");
pimScreenShotVo.setImageOssUrl("imageOssUrl");
pimScreenShotVo.setStatus(0);
pimScreenShotVo.setPcFlag(false);
pimScreenShotVo.setCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
pimScreenShotVo.setUrlType(0);
pimScreenShotVo.setMsg("msg");
final List pimScreenShotVos = Arrays.asList(pimScreenShotVo);
when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);

// Run the test
final PageInfo result = crawlerScreenShotServiceImplUnderTest.query(requestVo);

// Verify the results
}

@Test
public void testQuerySelectBoxData() {
// Setup

// Configure CrawerScreenShotTaskMapper.query(...).
final PimScreenShotVo pimScreenShotVo = new PimScreenShotVo();
pimScreenShotVo.setId(0L);
pimScreenShotVo.setUrl("url");
pimScreenShotVo.setImageOssUrl("imageOssUrl");
pimScreenShotVo.setStatus(0);
pimScreenShotVo.setPcFlag(false);
pimScreenShotVo.setCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
pimScreenShotVo.setUrlType(0);
pimScreenShotVo.setMsg("msg");
final List pimScreenShotVos = Arrays.asList(pimScreenShotVo);
when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);

// Run the test
final PimScreenShotTaskParamsDto result = crawlerScreenShotServiceImplUnderTest.querySelectBoxData();

// Verify the results
}

@Test
public void testFindExecutionScreenShotTaskCount() {
// Setup
when(mockCrawerScreenShotTaskMapper.findExecutionScreenShotTaskCount()).thenReturn(0);

// Run the test
final Integer result = crawlerScreenShotServiceImplUnderTest.findExecutionScreenShotTaskCount();

// Verify the results
assertEquals(0, result);
}

@Test
public void testFindCrawerScreenshotTaskByCreateTime() {
// Setup
final CrawlerScreenShotTaskSyncDto crawlerScreenShotTaskSyncDto = new CrawlerScreenShotTaskSyncDto();
crawlerScreenShotTaskSyncDto.setId(0L);
crawlerScreenShotTaskSyncDto.setUrl("url");
crawlerScreenShotTaskSyncDto.setSkuCode("skuCode");
crawlerScreenShotTaskSyncDto.setTaskType(0);
crawlerScreenShotTaskSyncDto.setStatus(0);
crawlerScreenShotTaskSyncDto.setLastModifyTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
crawlerScreenShotTaskSyncDto.setOperater("operater");
crawlerScreenShotTaskSyncDto.setMsg("msg");
final List expectedResult = Arrays.asList(crawlerScreenShotTaskSyncDto);

// Configure CrawerScreenShotTaskMapper.findCrawerScreenshotTaskByCreateTime(...).
final CrawlerScreenShotTaskSyncDto crawlerScreenShotTaskSyncDto1 = new CrawlerScreenShotTaskSyncDto();
crawlerScreenShotTaskSyncDto1.setId(0L);
crawlerScreenShotTaskSyncDto1.setUrl("url");
crawlerScreenShotTaskSyncDto1.setSkuCode("skuCode");
crawlerScreenShotTaskSyncDto1.setTaskType(0);
crawlerScreenShotTaskSyncDto1.setStatus(0);
crawlerScreenShotTaskSyncDto1.setLastModifyTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());
crawlerScreenShotTaskSyncDto1.setOperater("operater");
crawlerScreenShotTaskSyncDto1.setMsg("msg");
final List crawlerScreenShotTaskSyncDtos = Arrays.asList(crawlerScreenShotTaskSyncDto1);
when(mockCrawerScreenShotTaskMapper.findCrawerScreenshotTaskByCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(crawlerScreenShotTaskSyncDtos);

// Run the test
final List result = crawlerScreenShotServiceImplUnderTest.findCrawerScreenshotTaskByCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());

// Verify the results
assertEquals(expectedResult, result);
}

@Test
public void testQueryCrawlerDashboard() {
// Setup
when(mockCrawerScreenShotTaskMapper.queryCrawlerDashboard(0, 0, 0, new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(0);

// Run the test
final Integer result = crawlerScreenShotServiceImplUnderTest.queryCrawlerDashboard(0, 0, 0, new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());

// Verify the results
assertEquals(0, result);
}
}

报错了呢,不要慌,这个断言是为了检查你单元测试跑出来的结果是否符合预期的,如果你不想检查只想完成覆盖率,直接干掉就可以了(手动狗头)。

怎么样!刺不刺激,爽不爽,秒秒钟90多行的代码覆盖率就到了90%以上.

上面说过第一次进来会让你选择单元测试的模板,如果你要切换的话可以在单元测试类中按快捷键,Alt+M,或者通过Squaretest的菜单倒数第二个,下面这个就是按快捷键的效果,我选择的是这个模板,你们也可以借鉴。

OK,以上Squaretest部分就结束了,当然拉也不能高兴的太早,这个类算是比较成功的情况,很多时候还是要你自己小修小改的,毕竟它生成出来的测试数据可能完全匹配不上你的if else数据对吧,但这都很好改啊,这样就从自己分析if else变成了,debug程序了呀,哪里报错,debug过去,看看是不是生成的数据有问题,改个数据,就通过了,反正本人用的是很舒畅的,妥妥的节省70%的工作量。另外,公众 号Java精选,回复java面试,获取在线面试刷题神器。

解决了上面一个问题之后,又发现另一个问题,这个工具VO,DTO,Entity,Command,Model这种实体类来讲,一般这种实体类我们都用lombok的注解get,set,还有constract构造器等注解,但是这个工具只能生成这些实体类的构造器的单元测试,无法生成get set方法的单元测试,所以写了个base方法,实体类继承一下,简单的写两行带就好了,看下面代码:

@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
public abstract class BaseVoEntityTest {
protected abstract T getT();

private void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException,
InvocationTargetException {
T t = getT();
Class modelClass = t.getClass();
Object obj = modelClass.newInstance();
Field[] fields = modelClass.getDeclaredFields();
for (Field f : fields) {
boolean isStatic = Modifier.isStatic(f.getModifiers());
// 过滤字段
if (f.getName().equals("isSerialVersionUID") || f.getName().equals("serialVersionUID") || isStatic || f.getGenericType().toString().equals("boolean")
|| f.isSynthetic()) {
continue;
}
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass);
Method get = pd.getReadMethod();
Method set = pd.getWriteMethod();
set.invoke(obj, get.invoke(obj));
}
}

@Test
public void getAndSetTest() throws InvocationTargetException, IntrospectionException,
InstantiationException, IllegalAccessException {
this.testGetAndSet();
}

}

同样的方式我们在实体类上通过Squaretest生成单元测试,然后继承我上面写的那个base类,vo的单元测试代码稍加改动,如下

看run完之后,覆盖率100%,妥妥的,通过这两个解决方案,一天之内我们就把覆盖率搞到了60%以上,不要太刺激,大家可以用用试试哦,当然这个也不是纯为了应付差事写的单元测试,我们后续开发的时候,也可以用这个工具来生成,然后自测自己的代码,这样也是提升工作效率的嘛!

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!

(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!

特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注

文章有帮助的话,点在看,转发吧!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
荷兰军官:我们进入南海,遇到了解放军,他们没说这里是他们领土

荷兰军官:我们进入南海,遇到了解放军,他们没说这里是他们领土

阿龙聊军事
2026-05-28 15:58:13
上海滩大佬深谋远虑,送幼子奔赴延安,晚年得以安稳善终

上海滩大佬深谋远虑,送幼子奔赴延安,晚年得以安稳善终

唠叨说历史
2026-05-25 14:18:49
《家业》大结局:入赘生龙凤胎,昔日对头抢当带娃保姆

《家业》大结局:入赘生龙凤胎,昔日对头抢当带娃保姆

陈意小可爱
2026-05-31 01:13:31
未来10年中国最缺人的4个工科专业,毕业即高薪,不愁没工作

未来10年中国最缺人的4个工科专业,毕业即高薪,不愁没工作

狐狸先森讲升学规划
2026-05-30 06:30:03
1951年,陈毅发给黄金荣一把扫帚,老蒋得知后:陈毅真厉害

1951年,陈毅发给黄金荣一把扫帚,老蒋得知后:陈毅真厉害

派大鑫
2026-06-01 02:27:54
同事蹭我车回家,路过超市时买了1800块东西,要结账时我笑着说:你稍等一下,我去地下2层把车开上来

同事蹭我车回家,路过超市时买了1800块东西,要结账时我笑着说:你稍等一下,我去地下2层把车开上来

品读时刻
2026-05-28 09:06:31
巴萨6930万英镑签下戈登,纽卡为何此时放手?

巴萨6930万英镑签下戈登,纽卡为何此时放手?

坠入温柔晚风
2026-05-31 01:50:22
赵露思回乡为奶奶贺80大寿!砸重金办寿宴超孝顺,私下穿搭接地气

赵露思回乡为奶奶贺80大寿!砸重金办寿宴超孝顺,私下穿搭接地气

蒂蒂茱家
2026-05-31 17:24:19
同居七年未孕,真相撕开感情最凉的算计

同居七年未孕,真相撕开感情最凉的算计

朗威谈星座
2026-06-01 04:25:12
长腿美女,身材真好

长腿美女,身材真好

蓝色海洋009
2026-05-24 09:53:01
3轮拿7分仍下课!陈涛直面内情,体育总监乱干预,引援浪费资金

3轮拿7分仍下课!陈涛直面内情,体育总监乱干预,引援浪费资金

章民解说体育
2026-06-01 00:42:03
女生在性方面真正在意的是什么?

女生在性方面真正在意的是什么?

宇宙时空
2026-05-30 12:50:12
父亲是张艺谋又如何?张末连嫁两任老外遭家暴,差点走上肖华老路

父亲是张艺谋又如何?张末连嫁两任老外遭家暴,差点走上肖华老路

悦君兮君不知
2026-05-31 05:02:27
砍瓜切菜赢下系列赛第三场,上海久事男篮打出团队篮球,再赢一场就夺冠!

砍瓜切菜赢下系列赛第三场,上海久事男篮打出团队篮球,再赢一场就夺冠!

上观新闻
2026-06-01 04:14:13
杨鸣道破上海男篮制胜关键,夺冠将开启王朝

杨鸣道破上海男篮制胜关键,夺冠将开启王朝

逗比演员说体育
2026-06-01 04:16:38
别人怕以色列,中国不怕!欧美集体失声,凭什么中国敢动真格?

别人怕以色列,中国不怕!欧美集体失声,凭什么中国敢动真格?

贱议你读史
2026-05-31 00:22:08
霍英东二太冯坚妮95岁寿辰,四世同堂享福寿

霍英东二太冯坚妮95岁寿辰,四世同堂享福寿

风信子的花
2026-04-04 22:29:56
她穿上那条短裙时,就已经没有回头路了

她穿上那条短裙时,就已经没有回头路了

有态度网友ytd2993
2026-06-01 01:33:01
中到大雨、局部暴雨!江苏天气将突变!

中到大雨、局部暴雨!江苏天气将突变!

新浪财经
2026-06-01 02:22:19
G3上海110-77大胜广厦 球员评价:5人优秀,2人及格,2人低迷

G3上海110-77大胜广厦 球员评价:5人优秀,2人及格,2人低迷

篮球资讯达人
2026-05-31 21:23:12
2026-06-01 05:51:00
Java精选
Java精选
一场永远也演不完的戏
1791文章数 3859关注度
往期回顾 全部

科技要闻

戴尔诺基亚又回来了!AI重估老牌科技公司

头条要闻

特朗普生日白宫办格斗赛 近距离观赛花超100万美元

头条要闻

特朗普生日白宫办格斗赛 近距离观赛花超100万美元

体育要闻

阿森纳用最悲壮的方式,成就了巴黎王朝

娱乐要闻

朱军退休,正义虽迟但到,女方受惩

财经要闻

医学首席转岗搞科技,A股科技股遭遇巨震

汽车要闻

900V+3.2秒破百 领克10+&领克10上市16.99万元起

态度原创

游戏
家居
亲子
本地
军事航空

《巫师3》资料片“血与酒”发售十周年 纪念贺图发布

家居要闻

云栖 舒展如流云

亲子要闻

好想快进到这几期啊!

本地新闻

用剪纸的方式,打开江苏扬州

军事要闻

解放军代表质问日防卫大臣:日本何时道歉

无障碍浏览 进入关怀版