(原创)Junit中遇到FTP的上传下载该如何Mock

在测试过程中,遇到代码中存在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构造函数得到新的对象,该对象的方法可以打桩,官网示例如下


image-20200916195418725.png

示例关键代码段:

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进行打桩。

官网示例


image-20200916201605225.png

遇到的坑

坑一,运行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

原因

  1. 使用过旧的字节码生成工具进行类生成。

  2. 使用较旧的JDT编译应用。

解决方法


 org.javassist
 javassist
 3.20.0-GA
 test
 

坑二,采用方法二时,尽管使用spy,依然调用了方法内部,并没有被屏蔽。

原因


image-20200916171737303.png

注意:

//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

你可能感兴趣的:((原创)Junit中遇到FTP的上传下载该如何Mock)