赞
踩
当需要对静态类进行mock的时候:mockito-core的版本要在3.4以上,还要引入mockito-core依赖的其他jar,要引入mockito-inline,junit包要放在mockito-inline之前,引入的时候如果报错,请检查maven的setting文件,配置的仓库路径是否能正常下载、
- <dependencies>
- <!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <version>3.0.4</version>
- </dependency>
- <!-- 引入 测试 集成的版本低去掉-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <version>2.3.9.RELEASE</version>
- <exclusions>
- <exclusion>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-junit-jupiter</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-junit-jupiter</artifactId>
- <version>4.5.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>3.9.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-inline</artifactId>
- <version>4.5.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy</artifactId>
- <version>1.10.22</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy-agent</artifactId>
- <version>1.10.22</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
1、检查@ComponentScan 是否正常扫描到了路径
2、设置idea-file-project structure-moudles-选中模块-Sources-将test下面的java文件夹路径设置为tests(选中java点击tests)
3、选中要测试的service,右键-generate-选择test-
选择Junit的版本、测试名类称、路径(最好不要改了,与service的位置一致),选择要测试的方法
4、测试覆盖率配置
当写完测试类debug一下之后,edit Config....
选中测试类然后选class、选中下面红色的第一个,然后点-删去,点+添加进第二个,然后点击上图框住的小按钮,就可以查覆盖率了
@SpringBootTest()
@RunWith(SpringRunner.class)
方式一:
@InjectMock|@Mock:
@InjectMock:注释的是要测试的实现类,不是接口
@Mock:注释测试类serviceimpl用@Autowired引入的成员变量(mock后真实的方法不再调用)
但用Mockito.when(service.方法名(参数)).thenCallRealMethod();还是可以调真实的方法
@Spy:注释测试类serviceimpl用@Autowired引入的成员变量(spy真实的调用不调用要看写法)
但用Mockito.doReturn("不执行此方法").when(service).方法名(参数);还是可以不调用真实的方法
@Spy 会真实的执行对象的方法(如果方法报错,test直接报错)
@Mock 不会执行对象的方法(即使方法报错,test只会使用你设置的返回值,不影响流程)
方式二:
@Autowired| ReflectionTestUtils.setField();
@Autowired注释被注入mock的被测试的类
AopTestUtils.getTargetObject()、AopTestUtils.getUltimateTargetObject()
ReflectionTestUtils.setField();将其他的mock对象注入被测试的类中
@Autowired和@InjectMock最好不要一起使用,如果一起使用了
a、必须在test之前@Before中执行 MockitoAnnotations.openMocks(this);对mock初始化
b、测试的时候要用this.serviceimpl.方法名()测试 否则mock还会走真实的方法
需要手动再注入一下,不建议使用
ReflectionTestUtils.setField();
Student student=Mockito.mock(Student.class);
Student student=Mockito.spy(Student.class);
当方法实际传入的参数如果是null,则设置的mock的返回值会不生效,所以传入的参数Mockito.when(service.方法名(Mockito.anyString())).thenReturn(要返回的值);
service.方法名(null); //name上面的返回值失效了
Mockito.when(service.方法名(参数)).thenReturn(要返回的值); Mockito.when(service.方法名(参数)).thenCallRealMethod(); Mockito.when(service.方法名(参数)).thenThrow(new RuntimeException()); Mockito.doNothing().when(service).方法名(参数); Mockito.doReturn("不执行此方法").when(service).方法名(参数); new 对象的:MockedConstruction 静态方法:MockedStatic
1、mock 通过@Autowired注入的对象的方法(有返回值、无返回值)
2、mock 通过new的对象的方法
3、mock 调用的静态方法(有返回值、无返回值)
4、mock 同一个类的静态方法、私有方法、非私有方法
5、通过反射的方式测试私有方法
- public class Util {
- public static String getNum(){
- int i=1/0;
- return "123";
- }
- public static void skipNum(){
- int i=1/0;
- }
- }
- public class Sertn {
- public String setInedx(String shh ){
- int i=1/0;
- return "haha";
- }
- public void setInedxVoid(String shh ){
- int i=1/0;
- }
- private String getIndex(){
- int i=1/0;
- return "private";
- }
- }
- package com.springcloud.my.stock.service.impl;
-
- import com.springcloud.my.stock.bean.Student;
- import com.springcloud.my.stock.service.MyClassService;
- import com.springcloud.my.stock.service.MyTestService;
- import com.springcloud.my.stock.service.StudentService;
- import com.springcloud.my.stock.util.Sertn;
- import com.springcloud.my.stock.util.Util;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- @Service
- public class MyClassServiceImpl implements MyClassService {
-
- @Autowired
- private StudentService studentService;
-
- @Override
- public String doHomeWork(String name) {
- //有返回值
- String result= studentService.doHomeWork(name);
- Student student=new Student();
- student.setName(name);
- String result2= studentService.doHomeWork2(name,student);
- //无返回值
- studentService.doMathHomeWork();
- return result+"MyClassService"+result2;
- }
-
- /***静态方法 和new方法**/
- @Override
- public String getNumber() {
- studentService.doMathHomeWork();
- Util.skipNum();
- String num=Util.getNum();
- Sertn sertn=new Sertn();
- String hh=sertn.setInedx("");
- sertn.setInedxVoid();
- return num+hh;
- }
- /***自己类里面的方法**/
- @Override
- public String getOwnNumber() {
- studentService.doMathHomeWork();
- String gethahaha=getHaHa();
- String gethehehe=getHeHe();
- getTranslation();
- return gethahaha+gethehehe;
- }
- public void getTranslation(){
- int i=1/0;
- System.out.println("MyClassService getTranslation");
- }
- public String getHaHa(){
- int i=1/0;
- return "MyClassService haha";
- }
- private String getHeHe(){
- int i=1/0;
- return "hehe";
- }
- }
- package com.springcloud.my.stock.service;
-
- import com.springcloud.my.stock.bean.Student;
- import com.springcloud.my.stock.service.impl.MyClassServiceImpl;
- import com.springcloud.my.stock.util.Sertn;
- import com.springcloud.my.stock.util.Util;
- import lombok.SneakyThrows;
- import org.junit.Assert;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.mockito.*;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
-
- @SpringBootTest()
- @RunWith(SpringRunner.class)
- public class MyClassServiceTest {
- @InjectMocks
- //spy标签是因为要对MyClassServiceImpl 非测试的其他的方法进行mock
- @Spy
- private MyClassServiceImpl myClassService;
-
- /**如果是@Mock那么doReturn和thenReturn都不会执行真正的方法,
- * 如果是@Spy 那么doReturn不会执行真正的方法,thenReturn会执行真正的方法**/
- /**
- * 在这里Mock的成员变量如果不在下面设置返回值,返回的结果是返回类型的空值
- */
- @Mock
- private StudentService studentService;
-
- private AutoCloseable closeable;
-
- @Spy
- private MyClassServiceImpl myClassServiceSpy;
- @Before
- public void init() {
- closeable= MockitoAnnotations.openMocks(this);
- /***
- * MyClassServiceImpl 上的注解如果是@Autowired 而不是@InjectMocks 需要用下面的代码手动的注入
- * MyClassServiceImpl myClassService1= AopTestUtils.getTargetObject(myClassService);
- * ReflectionTestUtils.setField(myClassService1, "studentService",studentService);
- */
- }
- @After
- @SneakyThrows
- public void afterProject() {
- closeable.close();
- }
- @Test
- public void doHomeWorkTest() {
- //正常的测试 String result=myClassService.doHomeWork("张三");
- // 返回值 StudentService张三MyClassService张三
-
- //mock后
- String result=myClassService.doHomeWork("张三");
- Assert.assertEquals(result,"nullMyClassServicenull");
-
- /**无返回值的方法 可以直接跳过**/
- Mockito.doNothing().when(studentService).doMathHomeWork();
- /**如果studentService.doHomeWork()的参数是123 返回设置的返回值且不执行该方法***/
- Mockito.doReturn("不执行此方法").when(studentService).doHomeWork("123");
- Mockito.doReturn("不执行此方法111").when(studentService).doHomeWork("456");
- result=myClassService.doHomeWork("张三");
- Assert.assertEquals(result,"nullMyClassServicenull");
- result=myClassService.doHomeWork("123");
- Assert.assertEquals(result,"不执行此方法MyClassServicenull");
- result=myClassService.doHomeWork("456");
- Assert.assertEquals(result,"不执行此方法111MyClassServicenull");
- /**when thenReturn的写法***/
- Mockito.when(studentService.doHomeWork("456")).thenReturn("可能执行");
- result=myClassService.doHomeWork("456");
- Assert.assertEquals(result,"可能执行MyClassServicenull");
-
- /***无论studentService.doHomeWork()的参数是什么,都返回设定的值且不执行该方法**/
- Mockito.doReturn("不执行此方法").when(studentService).doHomeWork(Mockito.anyString());
- result=myClassService.doHomeWork("张三");
- Assert.assertEquals(result,"不执行此方法MyClassServicenull");
-
- /***当方法有多个参数时,参数必须都是Mockito. 的,或者都不是Mockito. 的 ,具体值的参数要用Mockito.eq包起来***/
- /*****不论传入的*****/
- Mockito.doReturn("*****").when(studentService)
- .doHomeWork2(Mockito.eq("李四"),Mockito.any());
- Mockito.doReturn("XXXXX").when(studentService)
- .doHomeWork2(Mockito.eq("李五"),Mockito.any());
- result=myClassService.doHomeWork("张三");
- Assert.assertEquals(result,"不执行此方法MyClassServicenull");
- result=myClassService.doHomeWork("李四");
- Assert.assertEquals(result,"不执行此方法MyClassService*****");
- result=myClassService.doHomeWork("李五");
- Assert.assertEquals(result,"不执行此方法MyClassServiceXXXXX");
-
- /***如果参数是对象***/
- Mockito.when(studentService.doHomeWork2(Mockito.any(),Mockito.any())).thenAnswer(mock->{
- /**1表示取方法的第一个参数**/
- Student student=mock.getArgument(1);
- if(student.getName().equals("哈哈")){
- return "Student";
- }else{
- return "";
- }
- });
- result=myClassService.doHomeWork("哈哈");
- Assert.assertEquals(result,"不执行此方法MyClassServiceStudent");
- result=myClassService.doHomeWork("111");
- Assert.assertEquals(result,"不执行此方法MyClassService");
-
- }
- //test的包要引入 import org.junit.Test;
- @Test
- public void getNumberTest() {
- //静态方法
- //无返回值的静态方法不需要处理直接就会跳过
- MockedStatic<Util> utilMockedStatic=Mockito.mockStatic(Util.class);
- //new 对象的方法
- //无返回值的方法不需要处理直接就会跳过
- MockedConstruction<Sertn> sertnMockedConstruction=
- Mockito.mockConstruction(Sertn.class,((mock,context)->{
- Mockito.doReturn("baba").when(mock).setInedx(Mockito.anyString());
- }));
- /**无返回值的方法 可以直接跳过**/
- Mockito.doNothing().when(studentService).doMathHomeWork();
- try{
- utilMockedStatic.when(()->Util.getNum()).thenReturn("000");
- String result=myClassService.getNumber();
- Assert.assertEquals(result,"000baba");
- //有返回值的静态方法
- }finally {
- //一定要关了。否则多个test会报错,
- //因为相同的类的MockedStatic、MockedConstruction一个线程只能有一个
- utilMockedStatic.close();
- sertnMockedConstruction.close();
- }
- }
- @Test
- public void getOwnNumberTest(){
- /***给myClassService加上 @Spy标签**/
- Mockito.doReturn("baba").when(myClassService).getHaHa();
- Mockito.doNothing().when(myClassService).getTranslation();
- String result=myClassService.getOwnNumber();
- //验证方法至少调用过一次
- verify(myClassService,atLeastOnce()).getHaHa();
- Assert.assertEquals(result,"000baba");
- }
- //测试私有方法
- @Test
- @SneakyThrows
- public void getHeHeTest(){
- //如果只是单纯的测试私有方法可以通过反射
- //如果想mock 私有方法,目前没有合适的方式 否则参考powermockito框架吧
- Method privateMethod =
- MyClassServiceImpl.class.getDeclaredMethod("getHeHe", null);
- privateMethod.setAccessible(true);
- String result= (String) privateMethod.invoke(MyClassServiceImpl.class.newInstance(),null);
- //验证返回值是否一致
- Assert.assertEquals(result,"babahaha");
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。