2

I want to mock a private method which has been called inside another method.

Following is the sample code, I have written.

Java code:

package org.mockprivatemethods;

public class AccountDeposit {
    // Instantiation of AccountDetails using some DI
    AccountDetails accountDetails;
    public long deposit(long accountNum, long amountDeposited){
        long amount = 0;
        try{
        amount =  accountDetails.getAmount(accountNum);
        updateAccount(accountNum, amountDeposited);
        amount= amount + amountDeposited;
        } catch(Exception e){
            // log exception
        }
        return amount;
    }

    private void updateAccount(long accountNum, long amountDeposited) throws Exception {
        // some database operation to update amount in the account      
    }

    // for testing private methods 
    private int sum(int num1, int num2){
        return num1+num2;
    }
}

class AccountDetails{

    public long getAmount(long accountNum) throws Exception{
        // some database operation returning amount in the account
        long amount = 10000L;
        return amount;
    }
}

Testclass:

package org.mockprivatemethods;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
public class TestAccountDeposit {

    @InjectMocks
    AccountDeposit accountDeposit;

    @Mock
    AccountDetails accountDetailsMocks;

    @Test
    public void testDposit() throws Exception{
        long amount = 200;
        when(accountDetailsMocks.getAmount(Mockito.anyLong()))
            .thenReturn(amount);
        // need to mock private method updateAccount
        // just like we tested the private method "sum()" using Whitebox
        // How to mock this private method updateAccount
        long totalAmount = accountDeposit.deposit(12345678L, 50);
        assertTrue("Amount in Account(200+50): "+totalAmount , 250==totalAmount);
    }

    @Test
    public void testSum(){
        try {
            int amount = Whitebox.invokeMethod(accountDeposit, "sum", 20, 30);
            assertTrue("Sum of (20,30): "+amount, 50==amount);
        } catch (Exception e) {
            Assert.fail("testSum() failed with following error: "+e);
        }

    }
}

We can test the private methods using Whitebox.invokeMethod(). My question is: Is there any to way mock the private method using Whitebox. Can we write something similar to below code to mock the updateAccount() as I do not want any database operation to be performed while testing the Deposit() method?strong text

when(accountDetailsMocks.getAmount(Mockito.anyLong()))
                .thenReturn(amount);

Any help is appreciated! Thanks!

S Kumar
  • 555
  • 7
  • 21
  • Honestly: I don't know. It is also something where I really would **not** invest much time on. You have to understand: you are testing implementation details here. The second you change your production code, your unit test breaks. Even a simple refactoring might break it. One should rework the production code to make it easier to test, that is much more of an useful investment. Beyond that, are you sure that these whitebox packages are still around? I ran into issues at some point, as newer versions of PowerMock(ito) would no longer support them... – GhostCat Jul 03 '18 at 09:13
  • After much of searching, I didn't find any better way to test private methods rather than using Whitebox.invokeMethod(). And, just for the sake of testing a method, it's not advisable to hamper the method visibility, that's why I found it cool. Sometimes in real scenarios, writing test cases for a particular method required to mock many private methods called in between. PowerMock(ito) is supporting Whitebox till 1.7. May be in future it would find another way to mock private methods. Test code coverage won't be complete without testing private methods. – S Kumar Jul 03 '18 at 10:12
  • Again: you don't test private methods. If you do so many things that separate testing is required, then one goes forward and refactors code into its own class. Of course, this is about balancing. In the end, I would rather opt for a package protected (instead of private) method when that helps with making testing easier. – GhostCat Jul 03 '18 at 10:47

0 Answers0