Mocking Sftp class skip method call

偶尔善良 提交于 2020-02-23 03:54:26

问题


public class SFTP {

    public Map<Report, TransferStatus> transfer(List<Report> reports) {
       //testing logic here
     }

    private ChannelSftp channelSftp;
    private Session session;


    private TransferStatus send(File file) {
                connect();

                send(stream, file.getName());      
    }


    private void send(FileInputStream stream, String name) throws SftpException, IOException {

        channelSftp.put(stream, fileNameWithId, new SftpLogMonitor(), ChannelSftp.OVERWRITE);
        stream.close();
    }


    private void connect() throws JSchException {

        if (session != null && channelSftp != null) {
            return;
        }

        JSch jsch = new JSch();

        jsch.addIdentity(sftpConfig.getSftpPublicKey());

        session = jsch.getSession(sftpConfig.getSftpUser(), sftpConfig.getSftpHost(), Integer.parseInt(sftpConfig.getSftpPort()));

        session.setUserInfo(new JschUserInfo());
        session.setConfig("StrictHostKeyChecking", "no");

        session.connect();

        Channel channel = session.openChannel("sftp");
        channelSftp = (ChannelSftp) channel;
        channelSftp.connect();
    }

Given the above, how can I avoid the calls to JSch objects. I want to avoid sending of the file to remote server and just want to validate test cases in transfer() method.

So far I have the following settings:

   private JSch jSch = mock(JSch.class);
    private Session session = mock(Session.class);
    private ChannelSftp sftp = mock(ChannelSftp.class);


    @Before
    public void setUp() throws Exception {
        when(jSch.getSession(eq(USERNAME), eq(HOSTNAME), eq(PORT))).thenReturn(session);
        when(session.openChannel("sftp")).thenReturn(sftp);
        //doNothing().when(sftp).put(Matchers.any());

    }

I don't want to exclude the call to put() or pass throw it to the next statement in the method.


回答1:


The main problem with using mockito here is that your connect() method depends on new JSch(). Mockito is not able to mock constructor calls. But you can change that with a little workaround, as suggested in Michael Feathers book. Just extract your new JSch() to the package private getter method

private void connect() throws JSchException {
    ...
    JSch jsch = getJSch();
    ...
}

JSch getJSch() {
    return new JSch();
}

Now in your test, you can override this method to return a mocked instance

private JSch jSch = mock(JSch.class);
private SFTP sftp = new SFTP(){
    @Override
    JSch getJSch() {
        return jSch;
    }
};

It's not the most elegant solution but it's the solution worth to consider. Especially if you don't want to do a lot of refactoring.



来源:https://stackoverflow.com/questions/46547763/mocking-sftp-class-skip-method-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!