单元测试

本文深入探讨单元测试的重要性,尤其在治疗代码懒惰症方面的作用。通过对比postman接口测试,阐述单元测试如何覆盖代码各场景,提前发现并解决问题。详细介绍非静态与静态方法的测试流程,包括使用mock模拟方法返回值,以及JUNIT4框架的应用。
摘要由CSDN通过智能技术生成

单元测试(静态和非静态方法的测试-------service篇)

1.单元测试的好处

在很多时候单元测试很恶心,每个人都不想写,因为它根本没用。目前我用的是postman测试接口,给我的感觉是我完全可以用它来测试代码,改变改变参数然后测一测,完全可以取代单元测试。
其实不然,为什么要用单元测试,从某种角度来说,主要是用来“治病”,那就是懒惰,单元测试需要考虑代码发生的各种情况,从而到达了每一个我们可能疏忽的点,在不经意间就发现并解决了问题。

2.单元测试的使用

本文只是单纯针对测试方法,并不对每一层(web,dao)做详细的单元测试

  • 非静态方法
    对于非静态方法来说,单元测试就再简单不过了,直接上图:

    笔者用的是mock 来模拟方法返回指定的信息,以及JUNIT4框架来进行单元测试。具体详细步骤如下:(IDEA)
    1.IDEA集成了单元测试,右键直接点击进入单元测试
    在这里插入图片描述
    2.在1处选择你需要单元测试的方法,2处选择@Before就是说在最开始对你的方法进行单元测试的时候需要初始化一些方法,而@after代表的意思就是 在单元测试结束时,运行的方法。此处仅仅简要说明一下,详细解释见下篇文章【对单元测试的注解解读】在这里插入图片描述
    3.完事具备,只欠东风
    开始增加注解,然后上大餐!
    (1)
    在这里插入图片描述
    增加启动类注解,启动,增加事务注解防止对数据库造成修改删除等操作。
    (这个类是一个抽象类,同样增加以上注解也可以放在测试类的上面)
    在这里插入图片描述
    通过继承抽象方法可以不用在每一次对一个类进行单元测试的时候都要添加重复的注解。
    在这里插入图片描述
    断言返回的数据对象的code码需要等于自己指定的值,如果不是你,那么说明单元测试错误。
  • 静态方法

对于静态方法,需要添加powerMock的相关注解,如下:

  • 添加引用的包也就是powerMock,可能是版本的问题,作者试了好久才找到这个版本的可以使用
    testCompile  group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0'
    testCompile  group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'
  • 增加注解
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({StaticClass.class,PrivateClass.class})
@SpringBootTest
@AutoConfigureMockMvc
@PowerMockIgnore( {"javax.management.*", "javax.net.*"})
@Transactional

这里有一点需要强调下,此处需要填写你想要mock的静态类:
在这里插入图片描述

  • 上关键代码
PowerMockito.mockStatic(StaticClass.class);
PowerMockito.when(StaticClass.sum(anyInt(),anyInt())).thenReturn(999);

以上两处就是mock静态类,以及mock需要返回的值

除了mock类,power mock的强大之处可是不仅仅这样,它还可以
mock私有方法以及声明的变量值都是可以mock的,关键代码如下:

私有方法
MemberModifier.stub(MemberMatcher.method(PrivateClass.class,"mockPrivate")).toReturn(0);
私有变量
 MemberModifier.field(PrivateClass.class, "d").set(privateClass , 0);

下面就是完整的静态类调用方法以及单元测试的简例:

  • 结构图
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 代码
* description:PrivateClass.java
*
* @author :Gavin
* @date :2020/1/9 9:14
**/

public class PrivateClass {
   private static int d = 9;
   public int sum(int b){
       PrivateClass privateClass = new PrivateClass();
       return privateClass.mockPrivate(5) + b;
   }
   public int variableSum(int e){
       return e + d;
   }
   private int mockPrivate(int c){
       return 3;
   }
}
/**
 * description:StaticClass.java
 *
 * @author :Gavin
 * @date :2020/1/8 17:04
 **/

public class StaticClass {
    public static int sum(int a,int b){
        return a+b;
    }
}
import org.springframework.stereotype.Service;

/**
 * description:TestPowerMock.java
 *
 * @author :Gavin
 * @date :2020/1/8 17:04
 **/
@Service
public class TestPowerMock {

    public void getStatic(int a,int b){
        System.out.println(StaticClass.sum(a,b));
    }
    public void  getPrivate(){
        PrivateClass privateClass  = new PrivateClass();
        System.out.println(privateClass.sum(2));
    }
    public void getVariableSum(){
        PrivateClass privateClass  = new PrivateClass();
        System.out.println(privateClass.variableSum(2));
    }
}
import com.inspur.cloud.vod.powermock.PrivateClass;
import com.inspur.cloud.vod.powermock.StaticClass;
import com.inspur.cloud.vod.powermock.TestPowerMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.membermodification.MemberMatcher;
import org.powermock.api.support.membermodification.MemberModifier;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;

/**
 * description:TestPowerMockTest.java
 *
 * @author :Gavin
 * @date :2020/1/8 17:08
 **/
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({StaticClass.class,PrivateClass.class})
@SpringBootTest
@AutoConfigureMockMvc
@PowerMockIgnore( {"javax.management.*", "javax.net.*"})
//为了解决使用powermock后,提示classloader错误 java.lang.NoClassDefFoundError: com.ibm.mq.jms.MQQueueConnectionFactory
@Transactional
public class TestPowerMockTest {
    private PrivateClass privateClass;
    @Autowired
    TestPowerMock testPowerMock;
    @Test
    public void getStatic() throws Exception {
        //真实数据
        System.out.println("静态方法==========真实数据==========静态方法");
        testPowerMock.getStatic(1,2);
        //mock数据
        System.out.println("静态方法==========mock数据==========静态方法");
        PowerMockito.mockStatic(StaticClass.class);
        PowerMockito.when(StaticClass.sum(anyInt(),anyInt())).thenReturn(999);
        testPowerMock.getStatic(1,2);


        System.out.println("私有方法==========真实数据==========私有方法");
        testPowerMock.getPrivate();
        MemberModifier.stub(MemberMatcher.method(PrivateClass.class,"mockPrivate")).toReturn(0);
        System.out.println("私有方法==========mock数据==========私有方法");
        testPowerMock.getPrivate();

        System.out.println("私有变量==========真实数据==========私有变量");
        testPowerMock.getVariableSum();
        PrivateClass privateClass = new PrivateClass();
        MemberModifier.field(PrivateClass.class, "d").set(privateClass , 0);
        System.out.println("私有变量==========mock数据==========私有变量");
        testPowerMock.getVariableSum();
    }
}
//单元测试powermock
    testCompile  group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0'
    testCompile  group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'
  • 以上就是静态类的调用方法,至于正常方法的单元测试,就不需要我多说了吧,直接上示例:
  • 非静态方法—结构
    在这里插入图片描述
    在这里插入图片描述
  • 非静态方法—代码
/**
 * description:NoStaticClass.java
 *
 * @author :Gavin
 * @date :2020/1/14 16:31
 **/

public class NonStaticClass {
    public int sum(int a ,int b){
        return a + b;
    }
}
import org.springframework.stereotype.Service;

/**
 * description:TTestPowerMock.kava
 *
 * @author :Gavin
 * @date :2020/1/8 17:04
 **/
@Service
public class TestPowerMock {
    public void nonStatic(){
        NonStaticClass nonStaticClass = new NonStaticClass();
        System.out.println(nonStaticClass.sum(2,4));
    }
}
//TestPowerMockTest .java
@Transactional
public class TestPowerMockTest {
    private PrivateClass privateClass;
    @Autowired
    TestPowerMock testPowerMock;
    @MockBean
    NonStaticClass nonStaticClass;
    @Test
    public void nonStatic() {
        //真实数据
        System.out.println("非静态方法==========真实数据==========非静态方法");
        testPowerMock.nonStatic();
        //mock数据
        System.out.println("非静态方法==========mock数据==========非静态方法");
        Mockito.when(nonStaticClass.sum(any(),any())).thenReturn(999);
    }

总算是总结了单元测试的一小部分,下次更新controller层的单元测试以及service层有关于涉及到sql的单元测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值