pannu
pannu

Reputation: 538

Mock internal method of a class

public Employe{
   public Double method1(int id){
      return method2(id);
   }
   public Double method2(int id) throws DatabaseException{
      //Some Code
      Employe e = employeRepositoy.getEmployeWithId(id);
      return e.getSalary();
   }
}

Now my two test scenarios are like this

@Test(expected = DatabaseException.class)
public void testemploye1() throws ServiceException, DatabaseException {
    Employe employe = Mockito.spy(new Employe());
    when(employe.method2(45585)).thenThrow(DatabaseException.class);
    employe .method1(45585);
}

@Test
public void testEmployee() throws ServiceException, DatabaseException {
    Employe employe = Mockito.spy(new Employe());
    when(employe.method2(45585)).thenReturn(3256);
    Double sal = employe .method1(45585);
    isTrue(sal.equals(3256));
}

First test scenerio runs fines and throws database exception. But in the second test scenrio instead of mocking the call goes into the internal method2 and throws null pointer exception. I am kind of suck here any help in this regard.

Upvotes: 0

Views: 3372

Answers (3)

glytching
glytching

Reputation: 48015

The NPE is occurring because employeRepositoy is null. Are you sure that testemploye1() is passing? As far as I can see it will fail with the same NPE, perhaps if you peek inside the actual exception cause you might see that testemploye1() is throwing a NPE too.

I think the testing approach is slightly 'off', if the intention is to test the behaviour of method2 (whether called directly or called via method1()) then I think you should be mocking employeRepositoy and injecting this and then providing it with expected behaviour. For example:

@Test(expected = DatabaseException.class)
public void testemploye1() {
  EmployeeRepository employeeRepository = Mockito.mock(EmployeeRepository.class);

  Employe employe = new Employe(employeeRepository);

  int id = 12345;
  when(employeeRepository.getEmployeWithId(id)).thenThrow(new DatabaseException());
  employe.method1(id);
}

@Test
public void testEmployee() {
  EmployeeRepository employeeRepository = Mockito.mock(EmployeeRepository.class);

  Employe employe = new Employe(employeeRepository);

  int id = 12345;
  Employe storedEmploye = ...;
  when(employeeRepository.getEmployeWithId(id)).thenReturn(storedEmploye);
  Double salary = employe.method2(id);
  assertEquals(storedEmploye.getSalary(), salary);
}

However, as other posters have noted this test approach does look rather odd.

Upvotes: 2

LT56
LT56

Reputation: 187

Impossible to use when(Object) for stubbing spies.

@Test
public void testEmployee() throws ServiceException, DatabaseException {
  Employe employe = Mockito.spy(new Employe());
  doReturn(3256).when(employe).method2(45585);    
  //when(employe.method2(45585)).thenReturn(3256);
  Double sal = employe .method1(45585);
  isTrue(sal.equals(3256));
}

Upvotes: 1

Plog
Plog

Reputation: 9612

I think for Spy's you need to use the following syntax for stubbing methods:

doReturn(100).when(employe).method2(45585);

instead of:

when(employe.method2(45585)).thenReturn(3256);

Upvotes: 1

Related Questions