java 为@ExceptionHandler 编写 JUnit 测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14605287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 16:48:00  来源:igfitidea点击:

Write JUnit test for @ExceptionHandler

javaspringrestspring-mvcjunit

提问by John B

I am writing a Rest service using Spring MVC. Here is the outline of the class:

我正在使用 Spring MVC 编写一个 Rest 服务。以下是课程大纲:

 @Controller
 public class MyController{

     @RequestMapping(..)
     public void myMethod(...) throws NotAuthorizedException{...}

     @ExceptionHandler(NotAuthorizedException.class)
     @ResponseStatus(value=HttpStatus.UNAUTHORIZED, reason="blah")
     public void handler(...){...}
 }

I have written my unit tests using the design posted here. The test is basically as follows:

我已经使用此处发布的设计编写了我的单元测试。测试基本如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(....)
public class mytest{

    MockHttpServletRequest requestMock;
    MockHttpServletResponse responseMock;
    AnnotationMethodHandlerAdapter handlerAdapter;

@Before
public void setUp() {
    requestMock = new MockHttpServletRequest();
    requestMock.setContentType(MediaType.APPLICATION_JSON_VALUE);
    requestMock.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

    responseMock = new MockHttpServletResponse();

    handlerAdapter = new AnnotationMethodHandlerAdapter();
}

@Test
public void testExceptionHandler(){
    // setup ....
    handlerAdapter.handle(...);

    // verify
    // I would like to do the following
    assertThat(responseMock.getStatus(), is(HttpStatus.UNAUTHORIZED.value()));
}

}

However, the call to handleis throwing the NotAuthorizedException. I have read that this is by design to be able to unit test that the method throws the appropriate exception, however I would like to write an automated test that the framework is handling this exception appropriately and that the class under test has implemented the handler appropriately. Is there a way to do this?

但是,对 的调用handle正在抛出NotAuthorizedException. 我已经读到这是设计使能单元测试该方法抛出适当的异常,但是我想编写一个自动化测试,框架正在适当地处理这个异常,并且被测类已经适当地实现了处理程序. 有没有办法做到这一点?

Please be aware that I do not have access to the actual code in a place where I could post it.

请注意,我无法在可以发布的地方访问实际代码。

Also, I am limited (for unfortunate reasons) to Spring 3.0.5 or 3.1.2.

此外,我(出于不幸的原因)仅限于 Spring 3.0.5 或 3.1.2。

采纳答案by Boris Treukhov

Consider using Spring 3.2 and its mvc-test-framework

考虑使用 Spring 3.2 及其mvc-test-framework

import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml")
public class WebMvcTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void getFoo() throws Exception {
        this.mockMvc.perform(
            get("/testx")
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            )
            .andExpect(status().isUnauthorized());
    }
}

Controller code

控制器代码

@Controller
public class MyController {

    public class MyException extends RuntimeException {
    };

    @RequestMapping("/testx")
    public void myMethod() {
        throw new MyException();

    }

    @ExceptionHandler(MyException.class)
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED, reason = "blah")
    public void handler() {
        System.out.println("handler processed");
    }
}

This "test" passes well.

这个“测试”顺利通过。

Disclaimer: currently I'm a noob in Spring MVC testing, actually it's my first test.
upd: Thanks to The Drake for the correction.

免责声明:目前我是 Spring MVC 测试的菜鸟,实际上这是我的第一次测试。
upd:感谢德雷克的更正

回答by Jonas Geiregat

Annotate your Exception Handling controller with @ControllerAdviceinstead of @Controller.

使用@ControllerAdvice而不是注释您的异常处理控制器@Controller

As Boris Treukhov noted when adding the @ExceptionHandlerannotation to a method in the controller that throws the exception will make it work but only from that specific controller.

正如鲍里斯·特鲁霍夫 (Boris Treukhov) 所指出的,在将@ExceptionHandler注释添加到引发异常的控制器中的方法时,将使其工作,但仅限于该特定控制器。

@ControllerAdvicewill allow your exception handeling methods to be applicable for your whole application not just one specific controller.

@ControllerAdvice将允许您的异常处理方法适用于您的整个应用程序,而不仅仅是一个特定的控制器。

回答by Joe

You could change @Test to

您可以将@Test 更改为

@Test(expected=NotAuthorizedException.class)

This would return true if the internals throw up that exception and false otherwise.

如果内部抛出该异常,则返回 true,否则返回 false。

This would also make the assertThat() unnecessary. You could write a second test that catches the NotAuthorizedException then you could inspect the responseMock under that condition then.

这也会使 assertThat() 变得不必要。您可以编写第二个测试来捕获 NotAuthorizedException,然后您可以在该条件下检查 responseMock。