Search code examples
javajunitmockito

Ignoring not void method inside testing method in Mockito


In class Account I have a method public Account reserveA() which I want to test, inside reserveA is called a method public Bank DAO.createB(). Is there a way to call reserveA() in test method but ignore call DAO.createB()? Non of these methods are void. I tried:

doNothing().when(Account).reserveA(param1, param2);

but it's not the proper way.


Solution

  • doNothing() is reserved only for void methods. If your method returns something, then you are required to do as well (or throw exception). Depending on complexity of your Account.reserveString(), you may need to mock some more than just this one method call if result is used somewhere else.

    Trying to use doNothing() on non-void method results in error:

    org.mockito.exceptions.base.MockitoException: 
    Only void methods can doNothing()!
    Example of correct use of doNothing():
        doNothing().
        doThrow(new RuntimeException())
        .when(mock).someVoidMethod();
    Above means:
    someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called
    

    Consider such classes:

    @Component
    public class BankDao {
        public BankDao() {}
    
        public void createVoid() {
            System.out.println("sth - 1");
        }
    
        public String createString(){
            return "sth - 2";
        }
    }
    
    @Service
    public class Account {
        @Autowired
        private final BankDao DAO;
    
        public Account(BankDao dao) {
            this.DAO = dao;
        }
        public void reserveVoid() {
            System.out.println("before");
            DAO.createVoid();
            System.out.println("after");
        }
        public void reserveString() {
            System.out.println(DAO.createString());
        }
    }
    

    For which Test class is made:

    @RunWith(MockitoJUnitRunner.class)
    public class AccountTest {
        @Mock
        private BankDao bankDao;
    
        @InjectMocks
        private Account account;
    
        @Test
        public void reserveVoid_mockBankDaoAndDontUseRealMethod() {
            doNothing().when(bankDao).createVoid();
            account.reserveVoid();
        }
    
        @Test
        public void reserveString_mockBankDaoAndDontUseRealMethod() {
            when(bankDao.createString()).thenReturn("nothing");
            account.reserveString();
        }
    }
    

    Running such a test will produce:

    nothing
    before
    after
    

    If you change @Mock to @Spy and remove lines with doNothing() and when(), then you'll be calling original methods. Result would be:

    sth - 2
    before
    sth - 1
    after