mockito单元测试
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mockito单元测试相关的知识,希望对你有一定的参考价值。
参考技术A 1、什么是Mock?mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为。比如说你需要调用B服务,可是B服务还没有开发完成,那么你就可以将调用B服务的那部分给Mock掉,并编写你想要的返回结,SpringBoot默认的Mock框架是Mockito,和junit一样,只需要依赖spring-boot-starter-test就可以了。
2、测试过程中常用注解
@RunWith 指定运行环境,例:
@RunWith(SpringRunner.class) Junit运行Spring的测试环境
@RunWith(MockitoJUnitRunner.class) Junit运行Mockito的运行环境,不会加载springboot上下文
@SpringBootTest 加载springboot上下文配置
@WebMvcTest(xxxController.class) 用于测试单个Controller,提供了自配置的MocMvc,可以不启动整个应用就可以以http请求的方 式测试Controller,不过这个注解不会去扫描@Service,@Mapper等注解,当调用这些服务时最好提前打桩,不然会报Error create bean这类异常
@Mock 用于模拟一个服务,例如测试的时候需用调用B服务,但是B服务没写 好,这是可以先Mock一个B服务
@InjectMocks 标注服务的实现类,创建一个实例,其余用@Mock注解创建的mock将被注入到用该实例中
@Before 每个测试方法执行前,执行一次
@After 每个测试方法执行完,执行一次
@Test 标注测试方法
3、测试Service的简单样例,( 注:目前项目中单元测试主要测试的是逻辑,第三方api及dao层都会屏蔽掉,所以不用加载整个上下文,建议用这种方式测试)
@RunWith(MockitoJUnitRunner.class)
public classTest
@Mock
private DataApi dataApi;
@InjectMocks
private DataServiceImpl dataService;
/*
* 准备数据
*/
@Before
public void baseInfo()
Entity entity=new Entity();
entity.setEndTime(1652544000);
//打桩,当DataService去调用dataApi的selectByPrimaryKey时,会返回模拟的entity数据,anyLong()指任意Long型参数
doReturn(entity).when(dataApi).selectByPrimaryKey(anyLong());
@Test
public void testGetData()
Stirng isOk=dataService.getData(123);
Assert.state("Ok".equals(isOk))//断言,返回预期结果,测试通过
// mock本类中的其他方法
DataServiceImpl dataService1 = Mockito.spy(dataService);
doReturn(false).when(dataService1).getData2(anyList(), any());
// 若需要多次调用一个方法,返回不同的结果,可以按顺序进行return;
when(dataService1.getData2(anyList(), any())).thenReturn("OK").thenReturn(null);
// 对测试类中私有变量赋值
// private int maxActive;
@Test
public void dataSourceTest()
try
Field apiField = FourthDaoConfiguration.class.getDeclaredField("maxActive");
FieldSetter.setField(fourthDaoConfiguration, apiField, 3);
DruidDataSource result =fourthDaoConfiguration.dataSource();
Assert.assertNotNull(result);
catch (Exception e)
// 对测试方法中返回的公用类做mock
@Test
public void updateSystemBalanceTest()
try
Long userId =1L;
Integer amount =10;
String actionCause ="aa";
String swiftNumber ="aa";
RLock fairLock =mock(RedissonLock.class);
doReturn(true).when(fairLock).tryLock(50, 60, TimeUnit.SECONDS);
doNothing().when(fairLock).unlock();
doReturn(fairLock).when(redissonClient).getLock(anyString());
int result =partnerAccountActionManager.updateSystemBalance(userId, amount, actionCause, swiftNumber);
Assert.assertTrue(result >0);
catch (Exception e)
e.printStackTrace();
4、测试Controller简单样例,模仿http发请求,载入springboot的上下文
@RunWith(SpringRunner.class)
@SpringBootTest
public class MockMvcTest
// 注入web环境的ApplicationContext容器
@Autowired
private WebApplicationContext context;
/**
* 模拟mvc测试对象
*/
private MockMvc mockMvc;
@Before
public void before() throws Exception
//获取mockmvc对象实例
mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
/*
mockMvc.perform 用于发送请求
MockMvcRequestBuilders用于指定请求方式,参数,媒体类型
*/
@Test
public void getInfo() throws Exception
mockMvc.perform(
MockMvcRequestBuilders.get("/xxx/getInfo")//请求方式,指定URL
.param("xxxx","1489")//请求参数
.param("xxxx","232")
.param("xxxx","0")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)//媒体类型
)
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0))//校验响应结果
.andReturn();//返回结果
android单元测试框架Mockito使用
单元测试,早些年时常听到这个概念,真的有去做的确实少,基本都是自己功能上的测试,开发完测试跑一边没啥问题就发布了。这几天花了点心思看了下MockIto框架,记录博文。
- MockIto官网文档在https://static.javadoc.io/org.mockito/mockito-core/2.23.0/org/mockito/Mockito.html。
- MockIto框架是基于原生JUnit4,JUnit4是整个单元测试的基础,他能够帮我我们开发者更快,更高效的进行单元测试
1.在mvp的模式上,我们建立一个P层叫LuckinTestPresenter,大概流程为:注册-》验证此账号是否允许注册,允许-》注册成功,具体为
/**
* 注册账号密码
* @param phone 账号
* @param passWord 密码
*/
public void register(String phone, String passWord) {
System.out.println("到达register");
}
/**
* 验证是否可以注册
* @param phone
* @param passWord
*/
public void verification(String phone, String passWord) {
System.out.println("到达verification");
if (!isLimit()) {
register(phone, passWord);
}
}
/**
* 注册之前检查这个手机号是否被限制
* @return
*/
public boolean isLimit() {
return false;
}
2:我们现在要在单元测试中,验证点击注册的时候程序是否有跑过verification方法,那么我们的单元测试案例为
public class LuckinPresenterTest {
@Test
public void check() {
//mockito会模拟LoginPresenterTest这个需要测试的class,返回一个LoginPresenterTest对象
LuckinTestPresenter luckinTestPresenter = Mockito.mock(LuckinTestPresenter.class);
//主动调用验证方法
luckinTestPresenter.verification("2018091280", "word");
//现在我们要了利用MockIto验证程序到这为止,是否走到了register(),方法如下
Mockito.verify(luckinTestPresenter).register("2018091280", "word");
}
}
run发现报错
为啥呢,因为你要验证的register()并没有被调用,为啥呢,看程序,应该执行的呀,这里需要注意的就是所哟Mock标记的类都是虚拟的,返回值都是null,也就是说你无法用一个为null的对象去调用register方法。如果我就要这么做呢,那就用spy标注吧。修改案例改为:
public class LuckinPresenterTest {
@Test
public void check() {
//mockito会模拟LoginPresenterTest这个需要测试的class,返回一个LoginPresenterTest对象
LuckinTestPresenter luckinTestPresenter = Mockito.spy(LuckinTestPresenter.class);
//主动调用验证方法
luckinTestPresenter.verification("2018091280", "word");
//现在我们要了利用MockIto验证程序到这为止,是否走到了register(),方法如下
Mockito.verify(luckinTestPresenter).register("2018091280", "word");
}
}
run结果为-》成功
2:现在有一个需求,我要测试当我isLimit()返回都会true时程序有没有走register,我又不想动原p层代码,那咋办呢,有办法,我们修改为
public class LuckinPresenterTest {
@Test
public void check() {
//mockito会模拟LoginPresenterTest这个需要测试的class,返回一个LoginPresenterTest对象
LuckinTestPresenter luckinTestPresenter = Mockito.spy(LuckinTestPresenter.class);
//主动调用验证方法
Mockito.when(luckinTestPresenter.isLimit()).thenReturn(true);//控住islimit返回true
luckinTestPresenter.verification("2018091280", "word");
//现在我们要了利用MockIto验证程序到这为止,是否走到了register(),方法如下
Mockito.verify(luckinTestPresenter).register("2018091280", "word");
}
}
run结果为
程序走过了verification,之后报错(就说明mock验证失败,程序没有走到register方法,因为你已经把isLimit返回值设为了true)。
相关方法为:
public class LuckinPresenterTest {
@Test
public void check() {
//mockito会模拟LoginPresenterTest这个需要测试的class,返回一个LoginPresenterTest对象
LuckinTestPresenter luckinTestPresenter = Mockito.spy(LuckinTestPresenter.class);
//控住isTourise返回true
Mockito.when(luckinTestPresenter.isLimit()).thenReturn(true);
//主动验证操作
luckinTestPresenter.verification("2018091280", "word");
//现在我们要了利用MockIto验证程序到这为止,是否走到了register(),方法如下
Mockito.verify(luckinTestPresenter).register("2018091280", "word");
//验证register的方法是否调用,并且是否为1次,并且参数一致
Mockito.verify(luckinTestPresenter, Mockito.times(1)).register("2018091280", "word");
//验证register的方法从未调用过
Mockito.verify(luckinTestPresenter, Mockito.never()).register("2018091280", "word");
//验证register的方法是否调用,并且是否为1次,参数忽略
Mockito.verify(luckinTestPresenter, Mockito.times(1)).register(Mockito.anyString(), Mockito.anyString());
}
}
以上是关于mockito单元测试的主要内容,如果未能解决你的问题,请参考以下文章