在测试过程中,遇到代码中存在static,final,new对象,ftp需要被mock时,一向很令人头疼,本篇文章,简单介绍一下,ftp的上传下载等方法应该如何mock。
我和我的同事lsj同时对该方法进行测试,采用了两种不同的方案,在下面会依次展示,以及过程中遇到的坑和解决方法。
实例
待测试代码举例,待测method为sendEmailAffix():
@Override
public Response sendEmailAffix(Request request) {
BaseDTO baseDTO;
SendEmailRequestDTO sendDTO = request.getRequestData();
String langType = getLanguageType(sendDTO.getEntId());
//获取邮件模板
MessageEmailTemplate messageEmailTemplate = new MessageEmailTemplate();
messageEmailTemplate.setTemplateType(ServiceConstants.MsgEmailTemplate.*TEMPLATE_TYPE_EMAIL*);
messageEmailTemplate.setFuncId(ServiceConstants.MsgEmailTemplate.*NEGOTIATION_SUC_CLOUD_SIGN_EMAIL*);
messageEmailTemplate.setLanguageType(langType);
MessageEmailTemplate emailTemplate = messageEmailTemplateMapper.queryTemplateContentById(messageEmailTemplate);
if (null == emailTemplate) {
baseDTO = new BaseDTO();
baseDTO.setStatus(false);
baseDTO.setMsg("mail template empty!");
*[log](http://log.info/)*[.info](http://log.info/)("templateID-33 mail template empty!");
return ResponseFactory.*getResponse*(baseDTO, request);
}
//替换模板占位符
String finalContent = emailTemplate.getTemplateContent(); sendDTO.setEmailPerson(emailTemplate.getSender());
sendDTO.setEmailTitle(emailTemplate.getTitle());
sendDTO.setEmailMsg(finalContent);
sendDTO.setAppendix(ServiceConstants.MsgEmailTemplate.*TEMPLATE_LANGUAGE_TYPE_CN*.equals(langType) ?
"洽谈备忘录.png" : "Negotiation Memo.png");
//授权发送邮件
BaseDTO resp = this.accreditSendEmail(sendDTO);
return ResponseFactory.*getResponse*(resp, request);
}
public BaseDTO accreditSendEmail(SendEmailRequestDTO sendEmailReq) {
BaseDTO baseDTO = new BaseDTO();
baseDTO.setStatus(false);
//下载本地FTP服务器的附件图片,上传到远端的FTP上
InputStream inputStream;
try {
inputStream = downloadPicFromLocalFTP(sendEmailReq);
} catch (IOException e) {
log.error("从gms FTP服务器下载文件失败!{}", e.getMessage());
baseDTO.setStatus(false);
baseDTO.setMsg("there is no picture on ftp");
return baseDTO;
}
//获得affixId
String sequence = messageEmailTemplateMapper.querySequence();//16位序列号
String blankString = " ";//12位空格
String affixId = MessagePush.SYSTEM_ID + MessagePush.DISPTYPE_02 + sequence + blankString + ServiceConstants.EmailSendState.EMAIL_SEQUENCE;
//上传签约图片到FTP2服务器
try {
uploadPic2RemoteFTP(inputStream, affixId);
} catch (Exception e) {
log.error("向邮件FTP服务器上传文件失败!{}", e.getMessage());
baseDTO.setStatus(false);
baseDTO.setMsg("upload to mcis's ftp fail");
return baseDTO;
}
//发送邮件和附件
SIPLauncherBean sipBean = sendEmailAccessory(sendEmailReq, affixId);
if (null != sipBean && null != sipBean.getRespHeader() && "0000000".equals(sipBean.getRespHeader().getMsgcde())) {
baseDTO.setStatus(true);
log.info("sendEmailAndAccessory调用结束,返回信息={}", sipBean.getRespHeader().getMsgcde());
}
log.info("SendEmailServiceImpl sendEmail end");
return baseDTO;
}
//下载FTP1服务器的附件图片
public InputStream downloadPicFromLocalFTP(SendEmailRequestDTO sendEmailReq) throws IOException {
FtpEntity ftpEntityIn = new FtpEntity(ConfigUtils.getProperty("ftp.A.ip"),
ConfigUtils.getProperty("ftp.A.username"),
ConfigUtils.getProperty("ftp.A.password"),
Integer.parseInt(ConfigUtils.getProperty("ftp.A.port")));
InputStream inputStream = null;
inputStream = new FTPUtil(ftpEntityIn).downloadToStream(
ConfigUtils.getProperty("ftp.A.picture.address"), sendEmailReq.getPictureName());
return inputStream;
}
//上传签约图片到FTP2服务器
public Boolean uploadPic2RemoteFTP(InputStream inputStream, String affixId) throws IOException {
FtpEntity ftpEntity = new FtpEntity(ConfigUtils.getProperty("ftp.B.ip"),
ConfigUtils.getProperty("ftp.B.username"),
ConfigUtils.getProperty("ftp.B.password"),
Integer.parseInt(ConfigUtils.getProperty("ftp.B.port")),
ConfigUtils.getProperty("ftp.B.picture.address"));
new FTPUtil(ftpEntity).uploadFile(inputStream, affixId);//上传时不带文件后缀
return true;//上传成功
}
可观察到,代码中需要测试的method和FTP上传下载method在同一个类中。需要连接FTP服务器进行上传下载图片,而简单的@Mock无法实现对于FTP的模拟。下面提供两种UT测试方法。
添加POM
首先,添加所需的POM依赖,引入powermock
org.powermock
powermock-api-mockito
${powermock.version}
test
org.mockito
mockito-all
org.javassist
javassist
org.powermock
powermock-module-junit4
${powermock.junit.version}
test
org.mockito
mockito-all
junit
junit
org.javassist
javassist
org.javassist
javassist
3.20.0-GA
test
PowerMockito准备
在你写的UT Class前先加@RunWith(PowerMockRunner.class)和@PrepareForTest
@RunWith(PowerMockRunner.class)
@PrepareForTest(SendEmailServiceImpl.class)
public class SendEmailAffixServiceUT extends UTContext {
@InjectMocks
private SendEmailServiceImpl sendEmailAffixService;
@Mock
private Launcher launcher;
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Mock
MessageEmailTemplateMapper messageEmailTemplateMapper;
方法一
对new FtpEntity()和new FTPUtil()采用PowerMockito.whenNew(),进行mock
FtpEntity ftpEntityIn = new FtpEntity(ConfigUtils.getProperty("ftp.A.ip"),
ConfigUtils.getProperty("ftp.A.username"),
ConfigUtils.getProperty("ftp.A.password"),
Integer.parseInt(ConfigUtils.getProperty("ftp.A.port")));
Junit代码如下
@Test
public void test_sendEmailAffix_success() throws Exception{
SendEmailRequestDTO sendDTO = new SendEmailRequestDTO();
sendDTO.setEmail("[email protected]");
sendDTO.setTransCode("0151fd79c6974f229d3001dc5889d6a8");
sendDTO.setPictureName("cloud_sign_0151fd79c6974f229d3001dc5889d6a8.png");
//获取邮件模板
EntUserLoginInfo entUserLoginInfo = new EntUserLoginInfo();
entUserLoginInfo.setLanguageType(ServiceConstants.UserLoginLanguageType.CN);
when(entUserLoginInfoMapper.queryLanguageTypeByEntId(anyString())).thenReturn(entUserLoginInfo);
MessageEmailTemplate messageEmailTemplateReq = new MessageEmailTemplate();
messageEmailTemplateReq.setTemplateType(ServiceConstants.MsgEmailTemplate.TEMPLATE_TYPE_EMAIL);
messageEmailTemplateReq.setFuncId(33);
MessageEmailTemplate emailTemplateRet = new MessageEmailTemplate();
emailTemplateRet.setSender("sender");
emailTemplateRet.setTitle("title");
emailTemplateRet.setTemplateContent("template content");
when(messageEmailTemplateMapper.queryTemplateContentById(any(MessageEmailTemplate.class))).thenReturn(emailTemplateRet);
//发送邮件接口
SIPLauncherBean sipLauncherBean = new SIPLauncherBean();
LauncherRespHeader respHeader = new LauncherRespHeader();
respHeader.setMsgcde("0000000");
sipLauncherBean.setRespHeader(respHeader);
Response sipResponse = ResponseFactory.getResponse(sipLauncherBean);
when(launcher.launch(any(Request.class), any(Class.class))).thenReturn(sipResponse);
FTPUtil mockFtpUtil = PowerMockito.mock(FTPUtil.class);
PowerMockito.whenNew(FTPUtil.class).withArguments(any(FtpEntity.class)).thenReturn(mockFtpUtil);
FtpEntity mockFtpEntity = PowerMockito.mock(FtpEntity.class);
PowerMockito.whenNew(FtpEntity.class).withArguments(anyString(), anyString(), anyString(),anyInt()).thenReturn(mockFtpEntity);
InputStream inputStream = PowerMockito.mock(InputStream.class);
when(mockFtpUtil.downloadToStream(anyString(), anyString())).thenReturn(inputStream);
when(mockFtpUtil.uploadFile(any(InputStream.class), anyString())).thenReturn(true);
Response resp = sendEmailAffixService.sendEmailAffix(RequestFactory.createRequest(sendDTO));
Assert.assertTrue(resp.getResponseData().isStatus());
}
注意:原理通过mock构造函数得到新的对象,该对象的方法可以打桩,官网示例如下
示例关键代码段:
FTPUtil mockFtpUtil = PowerMockito.mock(FTPUtil.class);
PowerMockito.whenNew(FTPUtil.class).withArguments(any(FtpEntity.class)).thenReturn(mockFtpUtil);
FtpEntity mockFtpEntity = PowerMockito.mock(FtpEntity.class);
PowerMockito.whenNew(FtpEntity.class).withArguments(anyString(), anyString(), anyString(),anyInt()).thenReturn(mockFtpEntity);
InputStream inputStream = PowerMockito.mock(InputStream.class);
when(mockFtpUtil.downloadToStream(anyString(), anyString())).thenReturn(inputStream);
when(mockFtpUtil.uploadFile(any(InputStream.class), anyString())).thenReturn(true);
方法二
对FTP uploadFile和downloadToStream方法进行打桩,屏蔽调用方法
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test
public void test_sendEmaiAffix_success_spy() throws Exception{
SendEmailServiceImpl spy = PowerMockito.spy(sendEmailAffixService);
SendEmailRequestDTO sendDTO = new SendEmailRequestDTO();
sendDTO.setEmail("[email protected]");
sendDTO.setTransCode("0151fd79c6974f229d3001dc5889d6a8");
sendDTO.setPictureName("cloud_sign_0151fd79c6974f229d3001dc5889d6a8.png");
//获取邮件模板
EntUserLoginInfo entUserLoginInfo = new EntUserLoginInfo();
entUserLoginInfo.setLanguageType(ServiceConstants.UserLoginLanguageType.CN);
when(entUserLoginInfoMapper.queryLanguageTypeByEntId(any(String.class))).thenReturn(entUserLoginInfo);
MessageEmailTemplate messageEmailTemplateReq = new MessageEmailTemplate();
messageEmailTemplateReq.setTemplateType(ServiceConstants.MsgEmailTemplate.TEMPLATE_TYPE_EMAIL);
messageEmailTemplateReq.setFuncId(33);
MessageEmailTemplate emailTemplateRet = new MessageEmailTemplate();
emailTemplateRet.setSender("sender");
emailTemplateRet.setTitle("title");
emailTemplateRet.setTemplateContent("template content");
when(messageEmailTemplateMapper.queryTemplateContentById(any(MessageEmailTemplate.class))).thenReturn(emailTemplateRet);
//发送邮件接口
SIPLauncherBean sipLauncherBean = new SIPLauncherBean();
LauncherRespHeader respHeader = new LauncherRespHeader();
respHeader.setMsgcde("0000000");
sipLauncherBean.setRespHeader(respHeader);
//下载上传接口
File file = temporaryFolder.newFile("test.jpg");
InputStream inputStream = new FileInputStream(file);
PowerMockito.doReturn(inputStream).when(spy).downloadPicFromLocalFTP(any(SendEmailRequestDTO.class));
PowerMockito.doReturn(true).when(spy).uploadPic2RemoteFTP(any(InputStream.class),any(String.class));
Response sipResponse = ResponseFactory.getResponse(sipLauncherBean);
when(launcher.launch(any(Request.class), any(Class.class))).thenReturn(sipResponse);
Response resp = spy.sendEmailAffix(RequestFactory.createRequest(sendDTO));
Assert.assertTrue(resp.getResponseData().isStatus());
}
原理,同一类内的方法进行打桩,需要@InjectMock该类,对这个生命的类变量进行spy,PowerMockito.spy(sendEmailAffixService)。然后,对spy的method进行打桩。
官网示例
遇到的坑
坑一,运行junit,mockito报错
"C:\Program Files\Java\jdk1.8.0_51\bin\java" -ea -Didea.launcher.port=7533 "-Didea.launcher.bin.path=D:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.3\bin" -Didea.junit.sm_runner -Dfile.encoding=UTF-8 -classpath "D:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.3\lib\idea_rt.jar;D:\Program Files (x86)\JetBrains\IntelliJ IDEA 2016.1.3\plugins\junit\lib\junit-rt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\rt.jar;D:\PROJECT\gms\svn-gms\gpmp-platform\gpmp-platform-service\target\test-classes;D:\PROJECT\gms\svn-gms\gpmp-platform\gpmp-platform-service\target\classes;D:\PROJECT\gms\svn-gms\gpmp-platform\gpmp-platform-dao\target\classes;D:\PROJECT\gms\svn-gms\gpmp-common\target\classes;D:\maven\repository\org\mybatis\mybatis\3.2.7\mybatis-3.2.7.jar;D:\maven\repository\org\mybatis\mybatis-spring\1.2.2\mybatis-spring-1.2.2.jar;D:\maven\repository\org\springframework\spring-tx\4.3.22.RELEASE\spring-tx-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-jdbc\4.3.22.RELEASE\spring-jdbc-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-beans\4.3.22.RELEASE\spring-beans-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-core\4.3.22.RELEASE\spring-core-4.3.22.RELEASE.jar;D:\maven\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;D:\maven\repository\com\alibaba\druid\1.0.9\druid-1.0.9.jar;D:\maven\repository\com\oracle\ojdbc14\10.2.0.4.0\ojdbc14-10.2.0.4.0.jar;D:\PROJECT\gms\svn-gms\gpmp-platform\gpmp-platform-serviceI\target\classes;D:\maven\repository\com\bocsoft\gaea\gaea-dubbo\1.1.4\gaea-dubbo-1.1.4.jar;D:\maven\repository\org\projectlombok\lombok\1.14.0\lombok-1.14.0.jar;D:\maven\repository\com\bocsoft\gaea\gaea-rudiment-service\1.1.9\gaea-rudiment-service-1.1.9.jar;D:\maven\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;D:\maven\repository\org\hibernate\hibernate-validator\5.3.4.Final\hibernate-validator-5.3.4.Final.jar;D:\maven\repository\org\jboss\logging\jboss-logging\3.3.0.Final\jboss-logging-3.3.0.Final.jar;D:\maven\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;D:\maven\repository\com\alibaba\dubbo\2.5.3\dubbo-2.5.3.jar;D:\maven\repository\com\alibaba\fastjson\1.2.69\fastjson-1.2.69.jar;D:\maven\repository\com\bocsoft\bocebiz\cbip\cbip-custfaceN-serviceI\0.0.1\cbip-custfaceN-serviceI-0.0.1.jar;D:\maven\repository\org\hibernate\javax\persistence\hibernate-jpa-2.0-api\1.0.1.Final\hibernate-jpa-2.0-api-1.0.1.Final.jar;D:\maven\repository\com\bocsoft\gaea\gaea-log\1.3.1\gaea-log-1.3.1.jar;D:\maven\repository\com\bocsoft\gaea\gaea-exception\1.0.1\gaea-exception-1.0.1.jar;D:\maven\repository\commons-beanutils\commons-beanutils\1.9.2\commons-beanutils-1.9.2.jar;D:\maven\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\maven\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;D:\maven\repository\org\springframework\spring-context\4.3.22.RELEASE\spring-context-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-context-support\4.3.22.RELEASE\spring-context-support-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-aspects\4.3.22.RELEASE\spring-aspects-4.3.22.RELEASE.jar;D:\maven\repository\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar;D:\maven\repository\org\springframework\spring-web\4.3.22.RELEASE\spring-web-4.3.22.RELEASE.jar;D:\maven\repository\org\springframework\spring-aop\4.3.22.RELEASE\spring-aop-4.3.22.RELEASE.jar;D:\maven\repository\com\bocsoft\gaea\gaea-logkafka\0.9.0-RELEASE\gaea-logkafka-0.9.0-RELEASE.jar;D:\maven\repository\org\slf4j\slf4j-api\1.7.26\slf4j-api-1.7.26.jar;D:\maven\repository\org\slf4j\log4j-over-slf4j\1.7.26\log4j-over-slf4j-1.7.26.jar;D:\maven\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\maven\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\maven\repository\org\codehaus\janino\janino\2.6.1\janino-2.6.1.jar;D:\maven\repository\org\codehaus\janino\commons-compiler\2.6.1\commons-compiler-2.6.1.jar;D:\maven\repository\net\sf\ehcache\ehcache\2.10.3\ehcache-2.10.3.jar;D:\maven\repository\org\apache\zookeeper\zookeeper\3.4.10\zookeeper-3.4.10.jar;D:\maven\repository\jline\jline\0.9.94\jline-0.9.94.jar;D:\maven\repository\io\netty\netty\3.10.5.Final\netty-3.10.5.Final.jar;D:\maven\repository\com\github\sgroschupf\zkclient\0.1\zkclient-0.1.jar;D:\maven\repository\commons-net\commons-net\3.3\commons-net-3.3.jar;D:\maven\repository\com\bocsoft\gaea\gaea-common\0.2.3-RELEASE\gaea-common-0.2.3-RELEASE.jar;D:\maven\repository\com\google\zxing\core\3.3.0\core-3.3.0.jar;D:\maven\repository\org\apache\poi\poi-ooxml\3.16\poi-ooxml-3.16.jar;D:\maven\repository\org\apache\poi\poi\3.16\poi-3.16.jar;D:\maven\repository\com\bocsoft\gaea\gaea-rudiment-util\1.1.9\gaea-rudiment-util-1.1.9.jar;D:\maven\repository\com\bocsoft\bocebiz\ezseci\ezseci\0.0.2-SNAPSHOT\ezseci-0.0.2-20160119.015308-1.jar;D:\maven\repository\com\bocsoft\bocebiz\ezsec\ezsec\0.0.2-SNAPSHOT\ezsec-0.0.2-20160119.020406-2.jar;D:\maven\repository\com\bocsoft\gaea\gaea-rudiment-security\1.2.2\gaea-rudiment-security-1.2.2.jar;D:\maven\repository\com\github\pagehelper\pagehelper\4.1.6\pagehelper-4.1.6.jar;D:\maven\repository\com\github\jsqlparser\jsqlparser\0.9.5\jsqlparser-0.9.5.jar;D:\maven\repository\com\bocsoft\gaea\gpmp-finder-serviceI\1.3-SNAPSHOT\gpmp-finder-serviceI-1.3-20200827.022901-3.jar;D:\maven\repository\com\qcloud\qcloud-java-sdk\2.0.1\qcloud-java-sdk-2.0.1.jar;D:\maven\repository\org\quartz-scheduler\quartz\2.2.1\quartz-2.2.1.jar;D:\maven\repository\c3p0\c3p0\0.9.1.1\c3p0-0.9.1.1.jar;D:\maven\repository\com\google\code\gson\gson\2.3.1\gson-2.3.1.jar;D:\maven\repository\org\apache\poi\poi-ooxml-schemas\3.16\poi-ooxml-schemas-3.16.jar;D:\maven\repository\org\apache\xmlbeans\xmlbeans\2.6.0\xmlbeans-2.6.0.jar;D:\maven\repository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;D:\maven\repository\com\github\virtuald\curvesapi\1.04\curvesapi-1.04.jar;D:\maven\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;D:\maven\repository\org\apache\commons\commons-collections4\4.1\commons-collections4-4.1.jar;C:\Program Files\Java\jdk1.8.0_51\jre\..\lib\jconsole.jar;C:\Program Files\Java\jdk1.8.0_51\jre\..\lib\tools.jar;D:\maven\repository\org\javassist\javassist\3.15.0-GA\javassist-3.15.0-GA.jar;D:\maven\repository\com\bocsoft\bocebiz\gms-hsm-serviceI\1.0.0-SNAPSHOT\gms-hsm-serviceI-1.0.0-20190509.023029-11.jar;D:\maven\repository\com\hazelcast\hazelcast\3.4.2\hazelcast-3.4.2.jar;D:\maven\repository\net\sourceforge\findbugs\annotations\1.3.2\annotations-1.3.2.jar;D:\maven\repository\com\eclipsesource\minimal-json\minimal-json\0.9.1\minimal-json-0.9.1.jar;D:\maven\repository\com\hazelcast\hazelcast-wm\3.4.2\hazelcast-wm-3.4.2.jar;D:\maven\repository\commons-io\commons-io\2.4\commons-io-2.4.jar;D:\maven\repository\org\apache\kafka\kafka-clients\0.9.0.1\kafka-clients-0.9.0.1.jar;D:\maven\repository\net\jpountz\lz4\lz4\1.2.0\lz4-1.2.0.jar;D:\maven\repository\org\xerial\snappy\snappy-java\1.1.1.7\snappy-java-1.1.1.7.jar;D:\maven\repository\org\slf4j\jcl-over-slf4j\1.7.13\jcl-over-slf4j-1.7.13.jar;D:\maven\repository\com\lmax\disruptor\3.3.2\disruptor-3.3.2.jar;D:\maven\repository\org\springframework\spring-expression\4.3.22.RELEASE\spring-expression-4.3.22.RELEASE.jar;D:\maven\repository\com\googlecode\junit-toolbox\junit-toolbox\1.8\junit-toolbox-1.8.jar;D:\maven\repository\junit\junit\4.12\junit-4.12.jar;D:\maven\repository\org\codehaus\jsr166-mirror\jsr166y\1.7.0\jsr166y-1.7.0.jar;D:\maven\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;D:\maven\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\maven\repository\org\mockito\mockito-core\1.9.5\mockito-core-1.9.5.jar;D:\maven\repository\org\springframework\spring-test\4.3.22.RELEASE\spring-test-4.3.22.RELEASE.jar;D:\maven\repository\org\mockito\mockito-all\1.9.5\mockito-all-1.9.5.jar;D:\maven\repository\javax\el\javax.el-api\2.2.4\javax.el-api-2.2.4.jar;D:\maven\repository\org\glassfish\web\javax.el\2.2.4\javax.el-2.2.4.jar;D:\maven\repository\com\bocsoft\gaea\gaea-cyclops\1.0.2-RELEASE\gaea-cyclops-1.0.2-RELEASE.jar;D:\maven\repository\com\hazelcast\hazelcast-client\3.4.2\hazelcast-client-3.4.2.jar;D:\maven\repository\com\hazelcast\hazelcast-spring\3.4.2\hazelcast-spring-3.4.2.jar;D:\maven\repository\com\esotericsoftware\kryo\kryo\2.22\kryo-2.22.jar;D:\maven\repository\joda-time\joda-time\2.3\joda-time-2.3.jar;D:\maven\repository\com\bocsoft\bocebiz\dims\dims-java-sdk\1.0.2\dims-java-sdk-1.0.2-jdk17.jar;D:\maven\repository\com\bocsoft\bocebiz\gpmp-smart-match-serviceI\1.1-SNAPSHOT\gpmp-smart-match-serviceI-1.1-20200819.090958-6.jar;D:\maven\repository\org\powermock\powermock-api-mockito\1.6.1\powermock-api-mockito-1.6.1.jar;D:\maven\repository\org\powermock\powermock-api-support\1.6.1\powermock-api-support-1.6.1.jar;D:\maven\repository\org\powermock\powermock-core\1.6.1\powermock-core-1.6.1.jar;D:\maven\repository\org\powermock\powermock-reflect\1.6.1\powermock-reflect-1.6.1.jar;D:\maven\repository\org\objenesis\objenesis\2.1\objenesis-2.1.jar;D:\maven\repository\org\powermock\powermock-module-junit4\1.6.1\powermock-module-junit4-1.6.1.jar;D:\maven\repository\org\powermock\powermock-module-junit4-common\1.6.1\powermock-module-junit4-common-1.6.1.jar" com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.bocsoft.bocebiz.gpmp.platform.tdg.email.SendEmailAffixServiceUT,test_sendEmailAffix_success
java.lang.VerifyError: Inconsistent stackmap frames at branch target 40
Exception Details:
Location:
com/bocsoft/bocebiz/gpmp/platform/tdg/email/SendEmailAffixServiceUT.()V @40: aload_1
Reason:
Type uninitializedThis (current frame, locals[1]) is not assignable to 'com/bocsoft/bocebiz/gpmp/platform/tdg/email/SendEmailAffixServiceUT' (stack map, locals[1])
Current Frame:
bci: @26
flags: { flagThisUninit }
locals: { uninitializedThis, uninitializedThis, top, 'java/lang/Object' }
stack: { 'java/lang/Object', 'java/lang/Object' }
Stackmap Frame:
bci: @40
flags: { flagThisUninit }
locals: { uninitializedThis, 'com/bocsoft/bocebiz/gpmp/platform/tdg/email/SendEmailAffixServiceUT' }
stack: { }
Bytecode:
0x0000000: 2a4c 1300 13b8 0019 03bd 000e 1300 1ab8
0x0000010: 001e b800 244e 2db2 0028 a500 0e2a 01c0
0x0000020: 002a b700 2ea7 0009 2bb7 0030 0157 2a00
0x0000030: 0000 0001 4c01 4d13 0032 b800 3503 bd00
0x0000040: 0e13 0037 b800 38b8 003b 4e2d b200 28a5
0x0000050: 002f 2dc1 003d 9900 20b8 0043 1300 44b8
0x0000060: 0035 120e 01b6 004a b600 4e01 b600 52c0
0x0000070: 0010 4da7 0008 2dc0 0010 4da7 000b bb00
0x0000080: 1059 b700 544d 2cb5 0057 a700 0301 3a05
0x0000090: 2ab8 005d b1
Stackmap Table:
append_frame(@40,Object[#12])
chop_frame(@46,1)
full_frame(@118,{Object[#12],Top,Top,Object[#14]},{Object[#12]})
full_frame(@123,{Object[#12],Top,Object[#16]},{Object[#12]})
full_frame(@126,{UninitializedThis},{UninitializedThis})
full_frame(@134,{UninitializedThis,Top,Object[#16]},{UninitializedThis})
full_frame(@141,{Object[#12]},{})
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetPublicMethods(Class.java:2902)
at java.lang.Class.getMethods(Class.java:1615)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.getTestMethods(PowerMockJUnit44RunnerDelegateImpl.java:93)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.(PowerMockJUnit44RunnerDelegateImpl.java:69)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl.(PowerMockJUnit47RunnerDelegateImpl.java:42)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl.(PowerMockJUnit49RunnerDelegateImpl.java:25)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:156)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.(JUnit4TestSuiteChunkerImpl.java:61)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.(AbstractCommonPowerMockRunner.java:32)
at org.powermock.modules.junit4.PowerMockRunner.(PowerMockRunner.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:98)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Process finished with exit code -1
原因
使用过旧的字节码生成工具进行类生成。
使用较旧的JDT编译应用。
解决方法
org.javassist
javassist
3.20.0-GA
test
坑二,采用方法二时,尽管使用spy,依然调用了方法内部,并没有被屏蔽。
原因
注意:
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
笔者尝试发现,当spy的方法是通过new对象引用的时候,使用when(spy.get(0)).thenReturn("foo");会进入到方法内部,而此种情况下doReturn("foo").when(spy).get(0);可以正确打桩。
引用
【1】https://www.jianshu.com/p/a3e551dc7313
【2】https://github.com/powermock/powermock/wiki/Mockito