junit MockMVC如何在同一个测试用例中测试异常和响应代码

a9wyjsp7  于 2022-11-11  发布在  其他
关注(0)|答案(5)|浏览(178)

我想Assert引发了一个异常,并且服务器返回一个500内部服务器错误。
为了突出显示意图,提供了一个代码片段:

thrown.expect(NestedServletException.class);
this.mockMvc.perform(post("/account")
            .contentType(MediaType.APPLICATION_JSON)
            .content(requestString))
            .andExpect(status().isInternalServerError());

当然,写isInternalServerError还是isOk并不重要,不管throw.except语句下面是否抛出异常,测试都会通过。
你打算怎么解决这个问题?

ego6inou

ego6inou1#

如果您有一个异常处理程序,并且想要测试特定的异常,您还可以Assert该示例在已解决的异常中是有效的。

.andExpect(result -> assertTrue(result.getResolvedException() instanceof WhateverException))

UPDATE(gavenkoa)不要忘记将带注解的@ExceptionHandler方法注入测试上下文,否则异常将在.perform()发生,而不是使用.andExpect()捕获它,基本上注册:

@ControllerAdvice
public class MyExceptionHandlers {
    @ExceptionHandler(BindException.class)
    public ResponseEntity<?> handle(BindException ex) { ... }
}

@Import(value=...)@ContextConfiguration(classes=...)或通过其它方式来实现。

ef1yzkbh

ef1yzkbh2#

您可以获得对MvcResult的引用和可能已解决的异常,并使用常规JUnitAssert进行检查...

MvcResult result = this.mvc.perform(
        post("/api/some/endpoint")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(someObject)))
        .andDo(print())
        .andExpect(status().is4xxClientError())
        .andReturn();

Optional<SomeException> someException = Optional.ofNullable((SomeException) result.getResolvedException());

someException.ifPresent( (se) -> assertThat(se, is(notNullValue())));
someException.ifPresent( (se) -> assertThat(se, is(instanceOf(SomeException.class))));
qzlgjiam

qzlgjiam3#

您可以尝试以下方法-
1.创建自定义匹配器

public class CustomExceptionMatcher extends
TypeSafeMatcher<CustomException> {

private String actual;
private String expected;

private CustomExceptionMatcher (String expected) {
    this.expected = expected;
}

public static CustomExceptionMatcher assertSomeThing(String expected) {
    return new CustomExceptionMatcher (expected);
}

@Override
protected boolean matchesSafely(CustomException exception) {
    actual = exception.getSomeInformation();
    return actual.equals(expected);
}

@Override
public void describeTo(Description desc) {
    desc.appendText("Actual =").appendValue(actual)
        .appendText(" Expected =").appendValue(
                expected);

}
}

1.在JUnit类中声明一个@Rule,如下所示-

@Rule
public ExpectedException exception = ExpectedException.none();

1.在测试用例中使用自定义匹配器作为-

exception.expect(CustomException.class);
exception.expect(CustomException
        .assertSomeThing("Some assertion text"));
this.mockMvc.perform(post("/account")
    .contentType(MediaType.APPLICATION_JSON)
    .content(requestString))
    .andExpect(status().isInternalServerError());

**P.S.:**我提供了一个通用的伪代码,您可以根据您的要求进行定制。

klh5stk1

klh5stk14#

我最近遇到了同样的错误,我没有使用MockMVC,而是创建了如下集成测试:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = { MyTestConfiguration.class })
public class MyTest {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void myTest() throws Exception {

        ResponseEntity<String> response = testRestTemplate.getForEntity("/test", String.class);

        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode(), "unexpected status code");

    }   
}

@Configuration
@EnableAutoConfiguration(exclude = NotDesiredConfiguration.class)
public class MyTestConfiguration {

    @RestController
    public class TestController {

        @GetMapping("/test")
        public ResponseEntity<String> get() throws Exception{
            throw new Exception("not nice");
        }           
    }   
}

这篇文章很有帮助:https://github.com/spring-projects/spring-boot/issues/7321

chy5wohz

chy5wohz5#

在控制器中:

throw new Exception("Athlete with same username already exists...");

在您的测试中:

try {
        mockMvc.perform(post("/api/athlete").contentType(contentType).
                content(TestUtil.convertObjectToJsonBytes(wAthleteFTP)))
                .andExpect(status().isInternalServerError())
                .andExpect(content().string("Athlete with same username already exists..."))
                .andDo(print());
    } catch (Exception e){
        //sink it
    }

相关问题