在intellij越来越普及的情况下,利用JUnit在intellij中进行测试就显得很基础了,但网上的资料总有误导的地方,这里记录一下。

总体而言,要开始单元测试,可以分为三步,添加相关的插件,添加相关的依赖,编写测试方法,下面依序说下。

一、添加相关的插件

在intellij中利用JUnit进行测试,需要三个插件,Junit,用来执行测试用例,JUnitGenerator V2.0,用来生成测试用例,Coverage,用来生成测试报告。

安装插件完毕,还需要对JUnit进行适当的设置:

Junit Generator设置

Setting --》 Other Setting--》 Junit Generator

更改输出路径,

Output Path:
${SOURCEPATH}/../../test/java/${PACKAGE}/${FILENAME}

更改默认单元测试框架,

Default Template:
Junit 4

更改JUnit4的默认模板,

Junit 4
test. $entry.packageName  $entry.packageName
<pre>$date</pre>  <pre>$today</pre>

二,添加相关的依赖

在maven项目中,添加如下的依赖:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>

三、开始编写测试方法

1.步骤

1)查看项目的project structure,确保:
Source Folders: src\main\java
Test Source Folders: src\test\java

2)在被测试的类中,选择 generate ->  JUnit Test -> JUnit 4

3)在生成的测试类中编写相关的测试代码

四、JUnit的注解

1.断言

编写单元测试方法的一个根本不同在于要用断言来表达测试是否通过。

@Test
public void testAdd() throws Exception {
int value = new Util().add(2,4);
Assert.assertEquals(6,value);
} org.junit.Assert
assertTrue(String message, boolean condition)
assertEquals(String message, Object expected,
Object actual)
assertArrayEquals(String message, Object[] expecteds, Object[] actuals)
assertNull(String message, Object object)
assertSame(String message, Object expected, Object actual)
assertThat(T actual, Matcher<? super T> matcher)

JUnit提供了各式各样的断言供使用,选择合适的即可。

2.@test的子属性

如果要测试异常或者时间,则可以利用@test注解的子属性。

excepted属性,异常测试
@Test (expected = Exception.class)
public void testDivideException() throws Exception {
new Junit_Test().divide(3,0);
fail("除数为零没有抛出异常");
} timeout属性,超时测试
@Test (timeout = 1000)
public void testDivideTimeout() throws Exception {
new Junit_Test_Demo().divide(6,3);

3.常用注解

@Test,标明是一个测试方法

@Before,在每个测试方法执行前都执行

@After,在每个测试方法执行完都执行

@BeforeClass,在测试类一开始就执行

@AfterClass,在测试类执行完毕执行

@Ignore,暂时忽略这个测试方法

4.高级注解

Rule:可以用来扩展JUnit的功能,改变测试方法的行为;
@ClassRule,类级别,执行测试类的时候只调用一次被注解的Rule
@Rule,方法级别,每个测试方法执行的时候都会调用被注解的Rule 内置的Rule
TemporaryFolder,创建临时目录或文件
ExternalResource,在测试之前创建资源,并在测试完成后销毁
TestName ,获取目前测试方法的名字
TestWatcher ,在每个触发点执行自定义的逻辑
Verifier ,在测试执行完成之后做一些校验,以验证测试结果是不是正确
ErrorCollector ,收集多个错误,并在测试执行完后一次过显示出来
@RunWith:默认BlockJunit4ClassRunner,可以指定特殊的Runner;

Suit,一次执行多个类的测试用例

Parameterized,批量指定多个待测参数

Category,对测试类中的被测试方法进行分类执行

Theories,为待测方法提供一组参数的排列组合

五,Mock

说到单元测试,就不能不提Mock,常用的mock框架很多,比较多用的是mockito和powermock。

Mockito
Mock技术框架,能让我们隔离外部依赖以便对我们自己的业务逻辑代码进行单元测试,在编写单元测试时,不需要再进行繁琐的初始化工作,在需要调用某一个接口时,直接模拟一个假方法,并任意指定方法的返回值。     Mockito的工作原理是通过创建依赖对象的proxy,所有的调用先经过proxy对象,proxy对象拦截了所有的请求再根据预设的返回值进行处理。Mockito对于Java接口使用接口代理的方式来模拟,对于Java类使用继承的方式来模拟(也即会创建一个新的Class类)。

PowerMock
PowerMock则在Mockito原有的基础上做了扩展,通过修改类字节码并使用自定义ClassLoader加载运行的方式来实现mock静态方法、final方法、private方法、系统类的功能。   从两者的项目结构中就可以看出,PowerMock直接依赖于Mockito,所以如果项目中已经导入了PowerMock包就不需要再单独导入Mockito包,如果两者同时导入还要小心PowerMock和Mockito不同版本之间的兼容问题。

1.流程

Mockito

    Mock
mock(Class classToMock);
mock(Class classToMock, String name) Stub
when(mock.someMethod()).thenReturn(value) 
when(mock.someMethod()).thenThrow(new RuntimeException)
when(mock.someMethod()).thenAnswer() exec

首先要利用mock来构造依赖,其次利用when语句来构造stub,然后就可以执行测试方法了。

其实还可以利用spy来构造依赖,但与mock构造有不同的地方:

mock
对于未指定处理规则的调用会按方法返回值类型返回该类型的默认值(如int、long则返回0,boolean则返回false,对象则返回null,void则什么都不做)

spy
未指定处理规则时则会直接调用真实方法

2.最佳实践

如何进行单元测试,每个公司都有不同的做法,一些最佳实践总结如下:

AIR原则
  automatic,必须使用断言,禁止使用输出进行验证
  independent,UT之间没有调用关系和前后关系
  repeatable,不与外界环境耦合,可随时执行
粒度
  只对单个的类进行测试,不检查跨类或跨系统的交互
  只对公开的接口进行测试
维护
  新增代码需要补充单元测试
  变更代码需要修正单元测试
编写单元测试的BCDE原则
  border,边界测试,特殊取值、特殊时间点、数据顺序等
  correct,正确的输入,并得到预期的结果
  design,与设计文档结合,编写单元测试
  error,强制错误信息输入(非法数据,异常流程),并得到预期结果
覆盖率
  语句覆盖率达到70%,分支覆盖率达到100%

3.利用Mock的一个例子

假如有person,dao和service三个类,其中dao是个接口,service依赖于dao,具体如下:

public class Person {
private final int id;
private final String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public interface IPersonDao {
Person getPerson(int id);
boolean update(Person person);
}
public class PersonService {
private final IPersonDao personDao; public PersonService(IPersonDao personDao) {
this.personDao = personDao;
} public boolean update(int id, String name) {
Person person = personDao.getPerson(id);
if (person == null) {
return false;
}
Person personUpdate = new Person(person.getId(), name);
return personDao.update(personUpdate);
}
}

利用mock来测试

 import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*; import org.mockito.Mock;
import org.mockito.Mockito.*;
import org.mockito.MockitoAnnotations; import java.util.List; /**
* PersonService Tester.
*
* @author <Authors name>
* @since <pre>07/01/2019</pre>
* @version 1.0
*/
public class PersonServiceTest { private IPersonDao mockDao;
private PersonService personService; @Before
public void before() throws Exception {
mockDao = mock(IPersonDao.class);
when(mockDao.getPerson(1)).thenReturn(new Person(1,"mst"));
when(mockDao.update(isA(Person.class))).thenReturn(true); personService = new PersonService(mockDao);
} @After
public void after() throws Exception {
} /**
*
* Method: update(int id, String name)
*
*/
@Test
public void testUpdate() throws Exception {
boolean result = personService.update(1,"md"); assertTrue(result); //验证是否执行过一次getPerson(1)
verify(mockDao,times(1)).getPerson(eq(1));
//验证是否执行过一次update
verify(mockDao,times(1)).update(isA(Person.class));
} @Test
public void testUpdateNotFind() throws Exception {
boolean result = personService.update(2, "md"); assertFalse( result); //验证是否执行过一次getPerson(1)
verify(mockDao, times(1)).getPerson(eq(2));
//验证是否执行过一次update
verify(mockDao, never()).update(isA(Person.class));
} @Mock
List list; public PersonServiceTest(){
MockitoAnnotations.initMocks(this);
} @Test
public void testList(){
when(list.add(isA(Object.class))).thenReturn(true);
list.add(2);
list.add(5);
boolean re = list.add(1);
assertTrue(re);
} }

其中演示了两种mock对象的构造,一种是手动构造,如22和27行,一种是注解构造,如69和72行。

在before方法中进行了依赖的mock和stub操作,进而在testUpdate中利用相应的依赖和stub进行测试逻辑的执行。

												

intellij JUnit mockito的更多相关文章

  1. JUnit + Mockito 单元测试(二)

    摘自: http://blog.csdn.net/zhangxin09/article/details/42422643 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 入门 ...

  2. JUnit + Mockito 单元测试(二)(good)

    import org.junit.Test; import org.mockito.Matchers; import org.mockito.Mockito; import java.util.Lis ...

  3. 基于Springboot+Junit+Mockito做单元测试

    前言 前面的两篇文章讨论过< 为什么要写单元测试,何时写,写多细 >和<单元测试规范>,这篇文章介绍如何使用Springboot+Junit+Mockito做单元测试,案例选取 ...

  4. JUnit + Mockito 单元测试

    原 JUnit + Mockito 单元测试(二) 2015年01月05日 17:26:02 sp42a 阅读数:60755 版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...

  5. Junit mockito 测试Controller层方法有Pageable异常

    1.问题 在使用MockMVC+Mockito模拟Service层返回的时候,当我们在Controller层中参数方法调用有Pageable对象的时候,我们会发现,我们没办法生成一个Pageable的 ...

  6. Junit mockito解耦合测试

    Mock测试是单元测试的重要方法之一. 1.相关网址 官网:http://mockito.org/ 项目源码:https://github.com/mockito/mockito api:http:/ ...

  7. JUnit+Mockito结合测试Spring MVC Controller

    [本文出自天外归云的博客园] 概要简述 利用JUnit结合Mockito,再加上spingframework自带的一些方法,就可以组合起来对Spring MVC中的Controller层进行测试. 在 ...

  8. Spring Test, JUnit, Mockito, Hamcrest 集成 Web 测试

    关于Spring 3.2 1. Spring 3.2 及以上版本自动开启检测URL后缀,设置Response content-type功能, 如果不手动关闭这个功能,当url后缀与accept头不一致 ...

  9. junit mockito

    package com.zendaimoney.util; import static org.mockito.Mockito.*;import static org.junit.Assert.*;i ...

随机推荐

  1. 开发--CentOS-7安装及配置

    开发|CentOS-7安装及配置 本文主要进行详细讲解CentOS7.5系统的安装过程,以及CentOS系统初始化技术.我并不想将这篇文章变成一个教程,尽管我将详细的进行每一步的讲解,enjoy! 前 ...

  2. 设计模式之(十一)代理模式(Proxy)

    软件开发行业有一个观点:任务问题都可以添加一个中间层来解决.代理模式也是这个思想下的产物. 首先看下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.就是把类委托给另外一个类,用这个类来控 ...

  3. CentOS 7.0 使用yum 安装 Mariadb

    第一步: 使用命令查看是否已经安装: mysql -u root -p 返回 Enter password:  时表示已经安装成功的,需要卸载安装. 第二步: 使用yum直接安装mariadb,注意带 ...

  4. Extjs 树菜单的自动展开数据的请求

    今天在做extjs开发的时候,在树菜单上遇到了一个坑,也许是我刚接触extjs 不熟的缘故 问题描述:后台设置的树自动展开,但是在前端总是只显示一条数据,但是数据确实都请求到了. 经过几个小时不屑的努 ...

  5. uni-app常用 HTML5+APP 设置

    1.锁定屏幕方向 锁定屏幕方向后屏幕只能按锁定的屏幕方向显示,关闭当前页面后仍然有效. 可再次调用此方法修改屏幕锁定方向或调用 unlockOrientation() 方法恢复到应用的默认值. 锁定屏 ...

  6. 【学习笔记】PYTHON网络爬虫与信息提取(北理工 嵩天)

    学习目的:掌握定向网络数据爬取和网页解析的基本能力the Website is the API- 1 python ide 文本ide:IDLE,Sublime    Text集成ide:Pychar ...

  7. Streaming Systems笔记

    一直心心念的<Streaming Systems>终于有了影印版本,京东110块钱果断买了,很惊喜还是彩印版本. 挖个坑,书看完后写一篇关于流式处理总结的笔记,大体翻看了一遍,总体来说流式 ...

  8. Linux shell 函数应用示例01

    函数Function的使用 定义函数 (1) 函数名称() {     ...     ... } (2) function 函数名称{     ...     ... } 调用函数         ...

  9. Nginx+Mysql调优

    使用nginx实现反向代理作用,具备负载均衡的功能.     接受客户端的请求 | nginx(宿主机) | |-------------------| web1 web2 (客户机)   原理: 与 ...

  10. nginx性能调优关键功能

     1. expires缓存时间优化作用:通过在服务器上设置合理的expires缓存时间.适合缓存的类型:静态文件:html,图片,js,css,xml都是缓存对象.优点:能够让用户不必每次访问都要重新 ...