当前位置: 首页 > 科技观察

小白搞SpringBoot单元测试

时间:2023-03-17 22:30:18 科技观察

大家好,我是田伟昌,今天给大家分享一个小伙的投稿。内容为:SpringBoot单元测试前言什么是单元测试?单元测试的目的:测试当前编写的代码是否正确,比如输入一组数据,就会输出预期的数据;如果输入错误的数据,会产生错误异常等。在单元测试中,我们需要保证被测系统是独立的(SUT没有任何DOC),即当被测系统通过测试时,它可以在任何环境中正常工作。编写单元测试时,只需关注单个类即可。不需要关注数据库服务、Web服务等组件,做过JavaWeb开发的同学都知道,后台开发不仅需要完成系统功能的开发,相应的单元测试类也必须同步写入,以保证系统的健壮性。基于SpringBoot开发的项目中的test包用于存放单元测试类,同时也提供了相应的注解来编写单元测试。本文总结了SpringBoot中基于??Mock的单元测试。环境:JDK1.8+,SpringBoot,mockito。单元测试的引入在SpringBoot中引入单元测试,只需要在pom文件中添加如下依赖,pom文件中提供了JUnit、SpringBootTest等常用的单元测试库。org.springframework.bootspring-boot-starter-test测试org.mockitomockito-core2.0.111-beta单元测试创??建每个单元测试类对应项目中的一个程序类,每个单元测试method对应于程序类中的一个方法。为了保证被测方法的正确性,至少需要设计四种测试用例,包括:正确用例、错误用例和边界用例。写的注释如下:测试类的位置位于项目的测试包下,包的层次结构与项目相同;测试类的命名规则通常是xxxTest.java,其中xxx代表被测试类的名称;测试类中的方法命名规则为testXxx,其中Xxx代表要测试的方法名;在测试方法中添加注解@Test;话不多说,我们直接开始吧。常用注解目前处于流行注解时代。我们先来了解几个相关的注解。注解@RunWith更改测试运行器,默认值org.junit.runner.Runner@Before初始化方法,在执行当前测试类的每个测试方法之前执行@Test测试方法,这里可以测试预期的异常和超时@Test(timeout=10000)超时测试方法,如果测试方法没有在指定时间内结束,junit会自动标记为失败@Transactional声明式事务管理,用于需要数据库事务管理的测试方法@Rollback(true)databaseback走开,避免测试数据污染数据库相关理论和技术要点,现在铺垫已经完成,下面,我们用代码来实现。代码实现我们做三层测试:controller、service、daoService层测试@RunWith(SpringRunner.class)@SpringBootTest(classes=Application.class)publicclassUserServiceTest{@AutowiredprivateUserServiceuserService;/***测试获取用户*/@Test(timeOut=300000)@TransactionalpublicvoidtestGetUser(){UserEntityuserEntity=userService.findByName("zhangSan");Assert.assertNotNull(userEntity);Assert.assertEquals("zhangSan",userEntity.getName());}}是不是很简单的?Controller层测试controller层,也可以称为网络请求测试。测试网络请求的情况在应用的Controller层比较常见。Spring测试框架提供了MockMvc对象,可以在没有客户端请求的情况下进行Web测试。测试开始前,需要搭建测试环境,通过@Before修改setup方法。通过MockMvcBuilders工具创建MockMvc对象。@RunWith(SpringRunner.class)@SpringBootTest(classes=Application.class)classUserControllerTest{@AutowiredprivateUserControlleruserController;@AutowiredprivateWebApplicationContext;privateMockMvcmockMvc;@Beforepublicvoidsetup(){mockMvc=MockMvcBuilders.standaloneSetup(userController).build;}/***获取用户列表*/@Test(timeOut=300000)publicvoidtestGetUserList()throwsException{Stringurl="/user/getUserList";MvcResultmvcResult=mockMvc.perform(MockMvcRequestBuilders.get(url)).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();Assert.assertNotNull(mvcResult);}}DAO层测试由于DAO层方法直接操作数据库,为了避免测试数据污染数据库,使用注解@Transactional和@Rollback返回测试数据测试完成后翻滚。@RunWith(SpringRunner.class)@SpringBootTestpublicclassScoreControllerTestNew{@AutowiredprivateUserDaouserDao;/***测试插入数据*/@Test@Rollback(value=true)@TransactionalpublicvoidtestInsert(){UseruserZhang=newUser();userZhang.setName("zhangSan");userZhang.setAge(23);userZhang.setGender(0);userZhang.setEmail("123@test.com");intn=userDao.insert(userZhang);Assert.assertEquals(1,n);}}去这里,三个层面的测试都已经完成了,我们来看看如何使用Mockito模拟数据库操作。使用Mockito模拟数据库操作引入web请求测试时使用了Mock技术。当被测模块(方法)依赖于外部系统(Web服务、中间件或数据库)时,通常会使用该技术。Mock的中文翻译是模仿、模拟、虚假。对于测试框架来说,就是构造一个simulated/false对象,这样我们的测试才能顺利进行。Mockito是目前最流行的单元测试模拟框架。使用Mock框架,我们可以虚拟出一个外部依赖,降低测试组件之间的耦合度,只关注代码的过程和结果,真正达到测试的目的。当web服务或数据库不可达时,可以进行mock,测试时可以在没有真实模块的情况下完成测试。常用的Mockito方法如下:方法介绍Mockito.mock(classToMock)Mockito.when(methodCall).thenReturn(value)参数匹配Mockito.doReturn(toBeReturned).when(mock).[method]参数匹配(直接执行)notJudgment)Mockito.when(methodCall).thenAnswer(answer))预期回调接口生成预期值Mockito.doNothing().when(mock).[method]不返回任何东西使用Mockito模拟单元测试后DAO层,得到新的单元测试类如下:@RunWith(SpringRunner.class)publicclassUserDaoTest{@MockBeanprivateUserDaouserDao;privateUseruserZhang=newUser();userZhang.setName("zhangSan");userZhang.setAge(23);@Beforepublicvoidsetup(){模拟。when(userDao.findByName("zhangSan")).willReturn(userZhang);Mockito.when(userDao.findByName("liSi")).willReturn(null);}@TestpublicvoidtestGetUser(){Assert.assertEquals(userZhang,userDao.findByName("zhangSan"));Assert.assertEquals(null,userDao.findByName("liSi"));}}关于mockito,请参考官网:https://site.mockito.org/使用代码用例来解释单元测试。空间有限。我先分享到这里。如有不当之处还请见谅并指出,本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。