web-dev-qa-db-ja.com

MockMVC同じテストケースで例外と応答コードをテストする方法

例外が発生し、サーバーが500内部サーバーエラーを返すことを表明したいと思います。

インテントを強調するために、コードスニペットが提供されています。

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

もちろん、isInternalServerErrorisOkのどちらを書いてもかまいません。 throw.exceptステートメントの下で例外がスローされても、テストはパスします。

これをどのように解決しますか?

18
Farmor

あなたは以下のように何かを試すことができます-

  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);
    
    }
    }
    
  2. JUnitクラスで@Ruleを次のように宣言します-

    @Rule
    public ExpectedException exception = ExpectedException.none();
    
  3. テストケースでカスタムマッチャーを使用する-

    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.:要件に応じてカスタマイズできる一般的な疑似コードを提供しました。

8

MvcResult への参照と、解決される可能性のある例外を取得し、一般的なjunitアサーションで確認できます...

          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))));
1
Eddie B

コントローラで:

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
    }
0
Erick Audet

例外ハンドラがあり、特定の例外をテストする場合は、解決された例外でインスタンスが有効であることをアサートすることもできます。

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