当前位置:   article > 正文

JAVA单元测试—JUNIT+Mockito_mockito-junit-jupiter

mockito-junit-jupiter

一、引入依赖:

当需要对静态类进行mock的时候:mockito-core的版本要在3.4以上,还要引入mockito-core依赖的其他jar,要引入mockito-inline,junit包要放在mockito-inline之前,引入的时候如果报错,请检查maven的setting文件,配置的仓库路径是否能正常下载、

  1. <dependencies>
  2. <!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. <version>3.0.4</version>
  7. </dependency>
  8. <!-- 引入 测试 集成的版本低去掉-->
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-test</artifactId>
  12. <version>2.3.9.RELEASE</version>
  13. <exclusions>
  14. <exclusion>
  15. <groupId>org.mockito</groupId>
  16. <artifactId>mockito-junit-jupiter</artifactId>
  17. </exclusion>
  18. <exclusion>
  19. <groupId>org.mockito</groupId>
  20. <artifactId>mockito-core</artifactId>
  21. </exclusion>
  22. </exclusions>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.mockito</groupId>
  26. <artifactId>mockito-junit-jupiter</artifactId>
  27. <version>4.5.1</version>
  28. <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.junit.jupiter</groupId>
  32. <artifactId>junit-jupiter-api</artifactId>
  33. <scope>test</scope>
  34. </dependency>
  35. <dependency>
  36. <groupId>junit</groupId>
  37. <artifactId>junit</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.mockito</groupId>
  42. <artifactId>mockito-core</artifactId>
  43. <version>3.9.0</version>
  44. <scope>test</scope>
  45. </dependency>
  46. <dependency>
  47. <groupId>org.mockito</groupId>
  48. <artifactId>mockito-inline</artifactId>
  49. <version>4.5.1</version>
  50. <scope>test</scope>
  51. </dependency>
  52. <dependency>
  53. <groupId>net.bytebuddy</groupId>
  54. <artifactId>byte-buddy</artifactId>
  55. <version>1.10.22</version>
  56. <scope>test</scope>
  57. </dependency>
  58. <dependency>
  59. <groupId>net.bytebuddy</groupId>
  60. <artifactId>byte-buddy-agent</artifactId>
  61. <version>1.10.22</version>
  62. <scope>test</scope>
  63. </dependency>
  64. </dependencies>

二、Test测试的配置:

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、选中下面红色的第一个,然后点-删去,点+添加进第二个,然后点击上图框住的小按钮,就可以查覆盖率了

 

 

三、注解的简单应用和语法:

1、注释测试类

  1. @SpringBootTest()

  2. @RunWith(SpringRunner.class)

2、注释成员变量

方式一:

@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还会走真实的方法

3、手动的mock

需要手动再注入一下,不建议使用

ReflectionTestUtils.setField();

Student student=Mockito.mock(Student.class);

Student student=Mockito.spy(Student.class);

4、参数:Mockito.any()(不校验参数类型)、Mockito.anyString()、Mockito.eq()等等

当方法实际传入的参数如果是null,则设置的mock的返回值会不生效,所以传入的参数Mockito.when(service.方法名(Mockito.anyString())).thenReturn(要返回的值);

service.方法名(null);   //name上面的返回值失效了

5、方法

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

6、Assert结果断言、verify行为验证

三、单元测试案例:

1、mock   通过@Autowired注入的对象的方法(有返回值、无返回值)

2、mock   通过new的对象的方法

3、mock   调用的静态方法(有返回值、无返回值)

4、mock   同一个类的静态方法、私有方法、非私有方法

5、通过反射的方式测试私有方法

四、代码示例

  1. public class Util {
  2. public static String getNum(){
  3. int i=1/0;
  4. return "123";
  5. }
  6. public static void skipNum(){
  7. int i=1/0;
  8. }
  9. }
  10. public class Sertn {
  11. public String setInedx(String shh ){
  12. int i=1/0;
  13. return "haha";
  14. }
  15. public void setInedxVoid(String shh ){
  16. int i=1/0;
  17. }
  18. private String getIndex(){
  19. int i=1/0;
  20. return "private";
  21. }
  22. }
  1. package com.springcloud.my.stock.service.impl;
  2. import com.springcloud.my.stock.bean.Student;
  3. import com.springcloud.my.stock.service.MyClassService;
  4. import com.springcloud.my.stock.service.MyTestService;
  5. import com.springcloud.my.stock.service.StudentService;
  6. import com.springcloud.my.stock.util.Sertn;
  7. import com.springcloud.my.stock.util.Util;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Service;
  10. @Service
  11. public class MyClassServiceImpl implements MyClassService {
  12. @Autowired
  13. private StudentService studentService;
  14. @Override
  15. public String doHomeWork(String name) {
  16. //有返回值
  17. String result= studentService.doHomeWork(name);
  18. Student student=new Student();
  19. student.setName(name);
  20. String result2= studentService.doHomeWork2(name,student);
  21. //无返回值
  22. studentService.doMathHomeWork();
  23. return result+"MyClassService"+result2;
  24. }
  25. /***静态方法 和new方法**/
  26. @Override
  27. public String getNumber() {
  28. studentService.doMathHomeWork();
  29. Util.skipNum();
  30. String num=Util.getNum();
  31. Sertn sertn=new Sertn();
  32. String hh=sertn.setInedx("");
  33. sertn.setInedxVoid();
  34. return num+hh;
  35. }
  36. /***自己类里面的方法**/
  37. @Override
  38. public String getOwnNumber() {
  39. studentService.doMathHomeWork();
  40. String gethahaha=getHaHa();
  41. String gethehehe=getHeHe();
  42. getTranslation();
  43. return gethahaha+gethehehe;
  44. }
  45. public void getTranslation(){
  46. int i=1/0;
  47. System.out.println("MyClassService getTranslation");
  48. }
  49. public String getHaHa(){
  50. int i=1/0;
  51. return "MyClassService haha";
  52. }
  53. private String getHeHe(){
  54. int i=1/0;
  55. return "hehe";
  56. }
  57. }
  1. package com.springcloud.my.stock.service;
  2. import com.springcloud.my.stock.bean.Student;
  3. import com.springcloud.my.stock.service.impl.MyClassServiceImpl;
  4. import com.springcloud.my.stock.util.Sertn;
  5. import com.springcloud.my.stock.util.Util;
  6. import lombok.SneakyThrows;
  7. import org.junit.Assert;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import org.junit.runner.RunWith;
  12. import org.mockito.*;
  13. import org.springframework.boot.test.context.SpringBootTest;
  14. import org.springframework.test.context.junit4.SpringRunner;
  15. @SpringBootTest()
  16. @RunWith(SpringRunner.class)
  17. public class MyClassServiceTest {
  18. @InjectMocks
  19. //spy标签是因为要对MyClassServiceImpl 非测试的其他的方法进行mock
  20. @Spy
  21. private MyClassServiceImpl myClassService;
  22. /**如果是@Mock那么doReturn和thenReturn都不会执行真正的方法,
  23. * 如果是@Spy 那么doReturn不会执行真正的方法,thenReturn会执行真正的方法**/
  24. /**
  25. * 在这里Mock的成员变量如果不在下面设置返回值,返回的结果是返回类型的空值
  26. */
  27. @Mock
  28. private StudentService studentService;
  29. private AutoCloseable closeable;
  30. @Spy
  31. private MyClassServiceImpl myClassServiceSpy;
  32. @Before
  33. public void init() {
  34. closeable= MockitoAnnotations.openMocks(this);
  35. /***
  36. * MyClassServiceImpl 上的注解如果是@Autowired 而不是@InjectMocks 需要用下面的代码手动的注入
  37. * MyClassServiceImpl myClassService1= AopTestUtils.getTargetObject(myClassService);
  38. * ReflectionTestUtils.setField(myClassService1, "studentService",studentService);
  39. */
  40. }
  41. @After
  42. @SneakyThrows
  43. public void afterProject() {
  44. closeable.close();
  45. }
  46. @Test
  47. public void doHomeWorkTest() {
  48. //正常的测试 String result=myClassService.doHomeWork("张三");
  49. // 返回值 StudentService张三MyClassService张三
  50. //mock后
  51. String result=myClassService.doHomeWork("张三");
  52. Assert.assertEquals(result,"nullMyClassServicenull");
  53. /**无返回值的方法 可以直接跳过**/
  54. Mockito.doNothing().when(studentService).doMathHomeWork();
  55. /**如果studentService.doHomeWork()的参数是123 返回设置的返回值且不执行该方法***/
  56. Mockito.doReturn("不执行此方法").when(studentService).doHomeWork("123");
  57. Mockito.doReturn("不执行此方法111").when(studentService).doHomeWork("456");
  58. result=myClassService.doHomeWork("张三");
  59. Assert.assertEquals(result,"nullMyClassServicenull");
  60. result=myClassService.doHomeWork("123");
  61. Assert.assertEquals(result,"不执行此方法MyClassServicenull");
  62. result=myClassService.doHomeWork("456");
  63. Assert.assertEquals(result,"不执行此方法111MyClassServicenull");
  64. /**when thenReturn的写法***/
  65. Mockito.when(studentService.doHomeWork("456")).thenReturn("可能执行");
  66. result=myClassService.doHomeWork("456");
  67. Assert.assertEquals(result,"可能执行MyClassServicenull");
  68. /***无论studentService.doHomeWork()的参数是什么,都返回设定的值且不执行该方法**/
  69. Mockito.doReturn("不执行此方法").when(studentService).doHomeWork(Mockito.anyString());
  70. result=myClassService.doHomeWork("张三");
  71. Assert.assertEquals(result,"不执行此方法MyClassServicenull");
  72. /***当方法有多个参数时,参数必须都是Mockito. 的,或者都不是Mockito. 的 ,具体值的参数要用Mockito.eq包起来***/
  73. /*****不论传入的*****/
  74. Mockito.doReturn("*****").when(studentService)
  75. .doHomeWork2(Mockito.eq("李四"),Mockito.any());
  76. Mockito.doReturn("XXXXX").when(studentService)
  77. .doHomeWork2(Mockito.eq("李五"),Mockito.any());
  78. result=myClassService.doHomeWork("张三");
  79. Assert.assertEquals(result,"不执行此方法MyClassServicenull");
  80. result=myClassService.doHomeWork("李四");
  81. Assert.assertEquals(result,"不执行此方法MyClassService*****");
  82. result=myClassService.doHomeWork("李五");
  83. Assert.assertEquals(result,"不执行此方法MyClassServiceXXXXX");
  84. /***如果参数是对象***/
  85. Mockito.when(studentService.doHomeWork2(Mockito.any(),Mockito.any())).thenAnswer(mock->{
  86. /**1表示取方法的第一个参数**/
  87. Student student=mock.getArgument(1);
  88. if(student.getName().equals("哈哈")){
  89. return "Student";
  90. }else{
  91. return "";
  92. }
  93. });
  94. result=myClassService.doHomeWork("哈哈");
  95. Assert.assertEquals(result,"不执行此方法MyClassServiceStudent");
  96. result=myClassService.doHomeWork("111");
  97. Assert.assertEquals(result,"不执行此方法MyClassService");
  98. }
  99. //test的包要引入 import org.junit.Test;
  100. @Test
  101. public void getNumberTest() {
  102. //静态方法
  103. //无返回值的静态方法不需要处理直接就会跳过
  104. MockedStatic<Util> utilMockedStatic=Mockito.mockStatic(Util.class);
  105. //new 对象的方法
  106. //无返回值的方法不需要处理直接就会跳过
  107. MockedConstruction<Sertn> sertnMockedConstruction=
  108. Mockito.mockConstruction(Sertn.class,((mock,context)->{
  109. Mockito.doReturn("baba").when(mock).setInedx(Mockito.anyString());
  110. }));
  111. /**无返回值的方法 可以直接跳过**/
  112. Mockito.doNothing().when(studentService).doMathHomeWork();
  113. try{
  114. utilMockedStatic.when(()->Util.getNum()).thenReturn("000");
  115. String result=myClassService.getNumber();
  116. Assert.assertEquals(result,"000baba");
  117. //有返回值的静态方法
  118. }finally {
  119. //一定要关了。否则多个test会报错,
  120. //因为相同的类的MockedStatic、MockedConstruction一个线程只能有一个
  121. utilMockedStatic.close();
  122. sertnMockedConstruction.close();
  123. }
  124. }
  125. @Test
  126. public void getOwnNumberTest(){
  127. /***给myClassService加上 @Spy标签**/
  128. Mockito.doReturn("baba").when(myClassService).getHaHa();
  129. Mockito.doNothing().when(myClassService).getTranslation();
  130. String result=myClassService.getOwnNumber();
  131. //验证方法至少调用过一次
  132. verify(myClassService,atLeastOnce()).getHaHa();
  133. Assert.assertEquals(result,"000baba");
  134. }
  135. //测试私有方法
  136. @Test
  137. @SneakyThrows
  138. public void getHeHeTest(){
  139. //如果只是单纯的测试私有方法可以通过反射
  140. //如果想mock 私有方法,目前没有合适的方式 否则参考powermockito框架吧
  141. Method privateMethod =
  142. MyClassServiceImpl.class.getDeclaredMethod("getHeHe", null);
  143. privateMethod.setAccessible(true);
  144. String result= (String) privateMethod.invoke(MyClassServiceImpl.class.newInstance(),null);
  145. //验证返回值是否一致
  146. Assert.assertEquals(result,"babahaha");
  147. }
  148. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/502652
推荐阅读
相关标签
  

闽ICP备14008679号