3

有点转贴,但是关于没有足够声誉的某些第 22 条规则意味着我不能对任何重复的线程发表评论!(咳嗽)

我正在尝试使用 Mockito 测试 try-catch 的 catch 块;是否可以让模拟抛出由正在测试的方法处理的异常?我不能使用 doThrow()...when()... 或 @Test(expected = Foo.class) 因为异常已处理。我想测试该方法是否正确处理异常。

@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;
    }
}

我希望能够存根我的“validatorObject”的行为,比如

doThrow(new CustomException()).when(validatorMock).validate();

有没有办法做到这一点?

这里的答案(使用 Junit 和 mockito 测试 catch 块逻辑)不起作用(我相信)因为异常在达到测试级别之前就被处理了。

非常感谢提示和想法!

4

2 回答 2

1

BDD风格解决方案

单独使用Mockito不是处理异常的最佳解决方案,请使用MockitoCatch-Exception

Mockito + Catch-Exception + AssertJ
given(otherServiceMock.bar()).willThrow(new MyException());

when(myService).foo();

then(caughtException()).isInstanceOf(MyException.class);
示例代码 依赖项
  • eu.codearte.catch-exception:catch-exception:1.3.3
  • org.assertj:assertj-core:1.7.0
坏处
  • 仅支持高达 1.10.8 的 Mockito
于 2018-06-23T17:08:48.780 回答
1

为什么不应该doThrow(..).when(..)...工作?

placeOrder方法捕获异常并返回可测试的结果:

@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());
    }
}

我已经用这两个文件进行了测试:

主要源代码:

//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 {}

测试源代码:

//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);
    }
}
于 2018-06-23T18:01:41.077 回答