Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking Sftp class skip method call

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.

like image 370
M06H Avatar asked Apr 20 '26 16:04

M06H


1 Answers

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.

like image 66
Sergii Bishyr Avatar answered Apr 22 '26 06:04

Sergii Bishyr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!