目录
一、为何用?
二、powermock的使用
1.引入依赖
2.单测代码
1.普通public方法
2.模拟构造器和final方法
3.模拟static静态方法
4.局部的final、private方法模拟
其它
Springboot 集成测试:
一、为何用?
Mockito 是一个针对 Java 的单元测试模拟框架,它与 EasyMock 和 jMock 很相似,都是为了简化单元测试过程中测试上下文 ( 或者称之为测试驱动函数以及桩函数 ) 的搭建而开发的工具。在有这些模拟框架之前,为了编写某一个函数的单元测试,程序员必须进行十分繁琐的初始化工作,以保证被测试函数中使用到的环境变量以及其他模块的接口能返回预期的值,有些时候为了单元测试的可行性,甚至需要牺牲被测代码本身的结构。单元测试模拟框架则极大的简化了单元测试的编写过程:在被测试代码需要调用某些接口的时候,直接模拟一个假的接口,并任意指定该接口的行为。这样就可以大大的提高单元测试的效率以及单元测试代码的可读性。
相对于 EasyMock 和 jMock,Mockito 的优点是通过在执行后校验哪些函数已经被调用,消除了对期望行为(expectations)的需要。其它的 mocking 库需要在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。
但是,Mockito 也并不是完美的,它不提供对静态方法、构造方法、私有方法以及 Final 方法的模拟支持。而程序员时常都会发现自己有对以上这些方法的模拟需求,特别是当一个已有的软件系统摆在面前时。幸好 , 还有 PowerMock。
PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 实现了对静态方法、构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。
二、powermock的使用
powermock项目GitHub地址:https://github.com/powermock/powermock
官方使用文档地址:https://github.com/powermock/powermock/wiki/Getting-Started
1.引入依赖 <properties> <powermock.version>2.0.2</powermock.version></properties><dependencies> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency></dependencies> 2.单测代码 1.普通public方法
1. 使用名称为PowerMockRunner的JUnit模块执行单元测试
2. 使用Mockito的@InjectMocks注解将待测试的实现类注入
3. 将生成MockDao,并注入到@InjectMocks指定的类中
@RunWith(PowerMockRunner.class)public class TcontentFeatureLabelServiceTest { @InjectMocks private TcontentFeatureLabelServiceImpl tcontentFeatureLabelService; @Mock private TcontentFeatureLabelMapper tcontentFeatureLabelMapper; @Test public void queryNamesByNo() { String[] features = {“qq”, “ww”}; TcontentFeatureLabel label = new TcontentFeatureLabel(); TcontentFeatureLabel label1 = new TcontentFeatureLabel(); label.setName(“hello”); label1.setName(“world”); List<TcontentFeatureLabel> list = Lists.newArrayList(label, label1); PowerMockito.when(tcontentFeatureLabelMapper.selectByExample(Mockito.any(TcontentFeatureLabelExample.class))).thenReturn(list); String result = tcontentFeatureLabelService.queryNamesByNo(features); Assert.assertEquals(“hello,world”, result); }} 2.模拟构造器和final方法
当需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,测试类上就需要添加注解@PrepareForTest!
public class CollaboratorWithFinalMethods { public final String helloMethod() { return “Hello World!”; }}
调用无参构造器,返回mock对象:
CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods();verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();
调用final方法:
when(collaborator.helloMethod()).thenReturn(“Hello Baeldung!”);String welcome = collaborator.helloMethod();Mockito.verify(collaborator).helloMethod();assertEquals(“Hello Baeldung!”, welcome); 3.模拟static静态方法 @RunWith(PowerMockRunner.class)@PrepareForTest({TypeSwitchUtil.class})public class TypeSwitchUtilTest { @Test public void buildTypeSwitch() { PowerMockito.mockStatic(TypeSwitchUtil.class); //PowerMockito.spy(TypeSwitchUtil.class);//代替模拟整个类,使用spy方法模拟部分协作类 String expect = “expect”; String input = “input”; PowerMockito.when(TypeSwitchUtil.buildTypeSwitch(input)).thenReturn(expect); String result = TypeSwitchUtil.buildTypeSwitch(input); Assert.assertEquals(expect, result); }} 4.局部的final、private方法模拟
代替模拟整个类,PowerMockito API允许使用spy方法模拟类的一部分。
private私有方法:
public class TeventScriptServiceImpl implements TeventScriptService {public String methodToTest() { return methodToPrivate(“input”); } private String methodToPrivate(String input) { return “REAL VALUE = ” + input; } } @RunWith(PowerMockRunner.class)@PrepareForTest({TeventScriptServiceImpl.class})public class TeventScriptServiceTest { @Test public void privateTest() throws Exception { String expected = “expected”; TeventScriptServiceImpl service = PowerMockito.spy(new TeventScriptServiceImpl()); PowerMockito.doReturn(expected).when(service, “methodToPrivate”, “input”); //PowerMockito.doNothing().when(service, “validConstantRightVar”, Mockito.any()); //PowerMockito.doReturn(entity).when(service, “expMetaExtendProcess”, Mockito.any(), Mockito.any()); String result = service.methodToTest(); Assert.assertEquals(expected, result); }}
final方法:
public class TcontentFeatureLabelServiceImpl implements TcontentFeatureLabelService { public final String methodFinal(String input) { return “hello final” + input; }} @RunWith(PowerMockRunner.class)@PrepareForTest({TcontentFeatureLabelServiceImpl.class})public class TcontentFeatureLabelServiceTest { @Test public void testMethodFinal() { TcontentFeatureLabelServiceImpl mockService = PowerMockito.spy(new TcontentFeatureLabelServiceImpl()); String expect = “expect”; PowerMockito.when(mockService.methodFinal(Mockito.anyString())).thenReturn(expect); String result = mockService.methodFinal(“test”); Assert.assertEquals(expect, result); }}
使用文档参考: ? ?
https://www.baeldung.com/intro-to-powermock
https://developer.ibm.com/zh/articles/j-lo-powermock/
其它 Springboot 集成测试: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency>
测试类上的注解:?
@RunWith(SpringJUnit4ClassRunner.class)@SpringBootTest(classes = OutGateWayApplication.class)