Java单元测试Mockito()

  本篇文章为你整理了Java单元测试Mockito()的详细内容,包含有 Java单元测试Mockito,希望能帮助你了解 Java单元测试Mockito。

  请给我的爱人来一杯mockito.在Java单元测试中,Mockito是一个常见的测试框架。我将在这篇文章中简单介绍一下Mockito的使用。欢迎大家留言讨论

  Test Double( 测试替身 )

  Dummy:不包含实作,在该次测试中完全用不上,只是为了满足编译而传入

  Stub: Method只会回传固定值,用来验证状态

  Spy:会记录SUT与DOC之间的行为互动,用来验证行为

  Fake: 会有接近原始物件的行为,但是会以简单的方式来做

  Mock:通过Mocking framework产生,可以快速的做到Dummy,Stub,Spy

  为什么要使用Mock

  Mock可以就是创建一个虚拟的对象,在测试环境中替换真实的对象,以便我们可以:

  验证该对象某些方法的调用情况,调用了多少次

  对这个对象的行为进行定义,来指定返回结构或者特定的动作。
 

  在使用Mock对象时,我们没有对一个方法/行为进行定义,则Mock对象方法就会返回这个方法返回类型的默认值

  

 @Test

 

   void add() {

   Random mock = Mockito.mock(Random.class);

   System.out.println(mock.nextInt()); // 此处拥有只用返回0,应为返回类型为int, int的默认值为0

   Mockito.verify(mock).nextInt();

   Mockito.verify(mock, Mockito.times(1)).nextInt();

  

 

  对Mock对象的方法、行为进行定义,俗称打桩

  

 @Test

 

   void add2() {

   Random mock = Mockito.mock(Random.class);

   Mockito.when(mock.nextInt()).thenReturn(100); // 这就是打桩

   int nextInt = mock.nextInt();// 此时每次都会返回100

   Mockito.verify(mock).nextInt(); // 判断这个方法有没有调用过

   Mockito.verify(mock, Mockito.times(1)).nextInt(); // 判断这个方法调用的具体次数

   Assertions.assertEquals(100,nextInt); // 断言

  

 

  @Mock: mock注解。在使用mock注解时,一定要使用MockitoAnnotations.openMocks来开启Mock注解

  

 @Mock

 

   private Random random;

   @Test

   void add3() {

   MockitoAnnotations.openMocks(this); // 开启Mock注解

   Mockito.when(random.nextInt()).thenReturn(100); // 这就是打桩

   int nextInt = random.nextInt();// 此时每次都会返回100

   Mockito.verify(random).nextInt(); // 判断这个方法有没有调用过

   Mockito.verify(random, Mockito.times(1)).nextInt(); // 判断这个方法调用的具体次数

   Assertions.assertEquals(100,nextInt); // 断言

  

 

  还有@BeforeEach和@AfterEach, 用于测试前准备和结束收尾

  Spy对象和@Spy注解

  spy()和mock()方法不同的是:

  被spy的对象会走真实的方法,而Mock对象不会

  spy方法的参数是对象实例,而mock参数是class实例

  

 @Spy

 

   private Random randomSpy; // 通过注解实现

   @Test

   void add4(){

   Random spy = Mockito.spy(new Random()); // 通过new实例实现

   int nextInt = randomSpy.nextInt();

   System.out.println(nextInt);

   Mockito.when(randomSpy.nextInt()).thenReturn(100); // 对spy对象打桩后,之后nextInt返回都是100

   for(int i=0; i i++){

   System.out.println(randomSpy.nextInt());

   Mockito.when(randomSpy.nextInt()).thenCallRealMethod(); // 再走真实的方法

  

 

  Mock的实际应用

  其实在mock的实际应用中,代码的规范才能更好的写出好的单元测试
 

  例如:

  

 void test1(){

 

   RestTemplateService restTempServ = new RestTempServImpl();

   String ans = restTempServ.sendMessage("ok");

   FileService fileService = new FileServiceImpl();

   fileService.saveFile("Hello");

   DBservice dbServ = new DBServImpl();

   dbServ.save(ans);

   System.out.println("test1");

  

 

  这样的一段代码,我们就很难写出很好的UT,其他服务的对象全部都new在代码中了。最好是写的时候就要考虑的UT的存在。此处,我们就需要对代码进行重构;

  

 @Autowired

 

   private RestTemplateService restTemplateService;

   @Autowired

   private FileService fileService;

   @Autowired

   private DBservice dBservice;

   void test2(){

   String ans = restTemplateService.sendMessage("ok");

   fileService.saveFile("Hello");

   dBservice.save(ans);

   System.out.println("test1");

  

 

  我们把其他服务的对象通过DI注入到对象中。

  这时候,我们UT测试:

  

class DemoTest2Test {

 

   @InjectMocks // 将剩下的Mock对象自动注册到该对象中

   @Spy

   private DemoTest2 demoTest2; // 这是需要测试的对象

   @Mock

   private RestTemplateService restTemplateService;

   @Mock

   private FileService fileService;

   @Mock

   private DBservice dBservice;

   @BeforeEach

   void before(){

   MockitoAnnotations.openMocks(this); // 开启Mock注解

   @Test

   void test2() {

  

 

  Mock实战

  需要测试的方法

  

public class RegistrationServiceImpl {

 

   @Autowired

   private DBservice dBservice;

   public User register(String name, String phone) throws Exception{

   if (name == null name.length() == 0){

   throw new RuntimeException("name is error");

   if (phone == null phone.length() 10){

   throw new RuntimeException("phone is error");

   User user;

   try {

   user = dBservice.getUser(name);

   } catch (SQLDataException e){

   throw new SQLNonTransientException("Database error");

   return user;

  

 

  UT代码

  

class RegistrationServiceImplTest {

 

   @InjectMocks // 将剩下的Mock对象自动注册到该对象中

   @Spy

   private RegistrationServiceImpl registrationService; // 这是需要测试的对象

   @Mock

   private DBServImpl dBservice;

   @BeforeEach

   void before(){

   MockitoAnnotations.openMocks(this); // 开启Mock注解

   @Test

   void register() throws Exception {

   String name = null;

   String phone = "123456789";

   try {

   registrationService.register(name, phone);

   Assertions.fail("fail"); // 走到这case直接挂了

   } catch (Exception e) {

   Assertions.assertTrue( e instanceof RuntimeException);

   Assertions.assertEquals("name is error", e.getMessage());

   name = "hardy";

   phone = null;

   try {

   registrationService.register(name, phone);

   Assertions.fail("fail"); // 走到这case直接挂了

   } catch (Exception e) {

   Assertions.assertEquals("phone is error", e.getMessage());

   phone = "123456";

   try {

   registrationService.register(name, phone);

   Assertions.fail("fail"); // 走到这case直接挂了

   } catch (Exception e) {

   Assertions.assertEquals("phone is error", e.getMessage());

   phone = "12345678963";

   // 数据库没有异常

   Mockito.when(dBservice.getUser("hardy")).thenCallRealMethod();

   User user = registrationService.register(name, phone);

   Assertions.assertTrue(user != null);

   // 数据库有异常

   Mockito.when(dBservice.getUser("hardy")).thenThrow(new SQLDataException("Database is error"));

   try {

   registrationService.register(name, phone);

   Assertions.fail("fail"); // 走到这case直接挂了

   } catch (Exception e) {

   Assertions.assertTrue(e instanceof SQLNonTransientException);

  

 

  
 

  

 dependencies 

 

   !-- https://mvnrepository.com/artifact/org.mockito/mockito-core --

   dependency

   groupId org.mockito /groupId

   artifactId mockito-core /artifactId

   version 4.3.1 /version

   scope test /scope

   /dependency

   !-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --

   dependency

   groupId org.junit.jupiter /groupId

   artifactId junit-jupiter-api /artifactId

   version 5.8.2 /version

   scope test /scope

   /dependency

   /dependencies

  

 

  
 

  以上就是Java单元测试Mockito()的详细内容,想要了解更多 Java单元测试Mockito的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: