Understanding Exception Handling on Mock objects
Mockito is the recommended and used mocking testing framework which provides varied function points to mock and verify interactions. It provides a parallel support to TestNG or JUnit for faster Test Driven Development (TDD) adoption in newer teams. In this edition of the write-up I would explore the concept of mocking with exception handling.
Lets consider a user credential validation login, before user getting authenticated into the system. If the credential validation fails, the system is expected to throw an application exception. However if it passes, the actual authentication to the system should
happen. With the familiarity with TestNG and Mockito, lets look the test case code
@Test(expectedException=UserValidationException.class)
public void testCredentialsValidation()
{ //create a mock to return false for validation - to fail login
UserCredentials credentials = mock(UserCredentials.class);
when(credentials.validate(anyString(),anyString())).thenReturn(false);
//Call the login service to gain entry
LoginService service = new LoginService(credentials);
service.loginuser("sample","sampl3");
}
Please note here that UserCredentials is only being mocked here, not the LoginService. The reason is to run the induced behaviour of the mocked UserCredentials on the actual LoginService functionality. A mocked object will behaviour only according to what has been induced.
Having looked at the test code, lets look at the actual logic implementation
public interface UserCredentials
{ public boolean validate(String username,String passwordtext);
}
public class LoginService
{ private UserCredentials credentials;
public LoginService(UserCredentials credentials)
{ this.credentials = credentials;
}
public void loginuser(String user, String passwd) throws UserValidationException
{ if(!credentials.validate(user,passwd))
throw new UserValidationException("Username or password invalid..");
//actual authentication process...
}
}
public UserValidationException extends RuntimeException
{ private String message;
public UserValidationException(String msg)
{ message = msg;
}
}
UserValidationException extends RuntimeException for brevity purposes, so that the test code signature is not affected. There is another methodology whereby we could induce behaviour of throwing an exception on the mocked object, even though the actual need not throw any exception.
doThrow(new UserValidation()).when(loginservice).loginuser(anyString(),anyString());
Unfortunately this is at the method level and not at the individual statement level. Am looking at options on mocking exceptions at the method statement level for the mocked objects. Any thoughts!