单元测试(静态和非静态方法的测试-------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的单元测试