Bit of a repost, but a certain catch-22 about not having enough reputation means I can't comment on any of the duplicate threads! (cough cough)
I'm trying to test the catch block of a try-catch using Mockito; is it possible to make a mock throw an exception that is handled by the method being tested? I can't use doThrow()...when()... or @Test(expected = Foo.class) because the exception is handled. I want to test that the method handles Exceptions properly.
@Controller
public class StockExchangeController {
public ModelAndView placeOrder(ModelAndView mav, MyObj myObj) {
try {
validator.validate(myObj); // Throws CustomException if validation fails
mav.setViewName("successPage");
} catch (CustomException ex) {
mav.setViewName("failPage");
}
return mav;
}
}
I'd like to be able to stub the behaviour of my "validatorObject", like
doThrow(new CustomException()).when(validatorMock).validate();
Is there a way to do this?
The answer here (Test catch block logic with Junit and mockito) doesn't work (I believe) because the exception is handled before it gets to test level.
Tips and thoughts much appreciated!
BDD Style Solution
Mockito alone is not the best solution for handling exceptions, use Mockito with Catch-Exception
Mockito + Catch-Exception + AssertJgiven(otherServiceMock.bar()).willThrow(new MyException());
when(myService).foo();
then(caughtException()).isInstanceOf(MyException.class);
Sample code
Dependencies
Why should doThrow(..).when(..)...
not work?
The placeOrder
method catches the exception and returns a testable result:
@RunWith(MockitoJUnitRunner.class)
public class TestStockExchangeController {
@Mock
Validator validator;
@Mock MyObj myObj;
@Test
public void testException() throws CustomException {
StockExchangeController sec = new StockExchangeController(validator);
doThrow(new CustomException()).when(validator).validate(myObj);
ModelAndView modelAndView = sec.placeOrder(new ModelAndView(), myObj);
assertEquals("failPage", modelAndView.getViewName());
}
}
I've tested with these two files:
Main source code:
//src/main/java/StockExchangeController.java
public class StockExchangeController {
private ValidationFactory factory;
public ModelAndView placeOrder(ModelAndView mav, MyObj myObj) {
Validator validator = factory.getValidator("S");
try {
validator.validate(myObj); // Throws CustomException if validation fails
mav.setViewName("successPage");
} catch (CustomException ex) {
mav.setViewName("failPage");
}
return mav;
}
}
class CustomException extends Exception {}
interface ValidationFactory {
Validator getValidator(String s);
}
class Validator {
public void validate(MyObj myObj) throws CustomException {}
}
class ModelAndView {
private String viewName;
public void setViewName(String viewName) {
this.viewName = viewName;
}
public String getViewName() {
return viewName;
}
}
class MyObj {}
Test source code:
//src/test/java/TestStockExchangeController.java
//various imports
@RunWith(MockitoJUnitRunner.class)
public class TestStockExchangeController {
@Mock
private Validator validator;
@Mock
private ValidationFactory validationFactory;
@InjectMocks
StockExchangeController target = new StockExchangeController();
@Test
public void testException() throws CustomException {
MyObj myObj = new MyObj();
when(validationFactory.getValidator(anyString())).thenReturn(validator);
doThrow(new CustomException()).when(validator).validate(myObj);
ModelAndView modelAndView = target.placeOrder(new ModelAndView(), myObj);
assertEquals("failPage", modelAndView.getViewName());
verify(validator).validate(myObj);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.