84

@ControllerAdviceアプリケーションにはコントローラーのセットがあり、これらのコントローラーのそれぞれで使用される特定のデータ要素を設定するアノテーションが付けられたクラスがあります。Spring MVC 3.2これらのコントローラーにJunitsを使用しています。Junit を実行すると、アプリをデプロイしてブラウザからリクエストを送信すると、コントロールがControllerAdvice正常に動作するクラスに移動しません。Tomcat

何か考えてください。

4

13 に答える 13

129

@eugene-to からの回答と別の同様の回答を使用した後、制限が見つかり、Spring で問題が発生しました: https://jira.spring.io/browse/SPR-12751

その結果、Spring テスト@ControllerAdviceでは、4.2 でビルダーにクラスを登録する機能が導入されました。Spring Bootを使用している場合は、1.3.0 以降が必要です。

この改善により、スタンドアロン セットアップを使用している場合は、次のように 1 つ以上のControllerAdviceインスタンスを設定できます。

mockMvc = MockMvcBuilders.standaloneSetup(yourController)
            .setControllerAdvice(new YourControllerAdvice())
            .build();

注:名前setControllerAdvice()からすぐにわかるとは限りませんが、var-args 署名があるため、多くのインスタンスを渡すことができます。

于 2015-02-25T19:24:44.313 に答える
42

@ExceptionHandler でアノテーションが付けられたメソッドを持つ @ControllerAdvice でアノテーションが付けられたクラス MyControllerAdvice があるとします。MockMvc の場合、このクラスを例外リゾルバーとして簡単に追加できます。

@Before
public void beforeTest() {
    MockMvc mockMvc = standaloneSetup(myControllers)
        .setHandlerExceptionResolvers(createExceptionResolver())
        .build();
}

private ExceptionHandlerExceptionResolver createExceptionResolver() {
    ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
        protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
            Method method = new ExceptionHandlerMethodResolver(MyControllerAdvice.class).resolveMethod(exception);
            return new ServletInvocableHandlerMethod(new MyControllerAdvice(), method);
        }
    };
    exceptionResolver.afterPropertiesSet();
    return exceptionResolver;
}
于 2013-10-12T19:39:23.017 に答える
19

このコードは私のために働いています:

public class MyGlobalExceptionHandlerTest {

    private MockMvc mockMvc;

    @Mock
    HealthController healthController;

    @BeforeTest
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(healthController)
            .setControllerAdvice(new GlobalExceptionHandler())
            .build();
    }

    @Test(groups = { "services" })
    public void testGlobalExceptionHandlerError() throws Exception {
        Mockito.when(healthController.health())]
               .thenThrow(new RuntimeException("Unexpected Exception"));
        mockMvc.perform(get("/health")).andExpect(status().is(500));
    }
}
于 2017-07-11T13:28:37.707 に答える
7

私はかなり長い間同じことで苦労してきました。多くの掘り下げの後、最良のリファレンスはSpringのドキュメントでした:

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework

つまり、コントローラーとそのメソッドを単純にテストする場合は、単純な Spring MVC 構成を作成する「standaloneSetup」メソッドを使用できます。これには、@ControllerAdvice で注釈を付けたエラー ハンドラーは含まれません。

private MockMvc mockMvc;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
}

// ...

エラーハンドラーを含むより完全なSpring MVC 構成を作成するには、次のセットアップを使用する必要があります。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("test-servlet-context.xml")
public class AccountTests {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Autowired
    private AccountService accountService;

    // ...

}
于 2013-04-08T10:27:51.190 に答える
0

特定の回答を期待する前に、より多くの情報と、実際のコードや構成ファイルを提供する必要があります。とはいえ、あなたが提供した小さなことに基づいて、注釈付きの Bean がロードされていないようです。

以下をテスト applicationContext.xml (または同等の spring config ファイルを使用している場合) に追加してみてください。

<context:component-scan base-package="com.example.path.to.package" />

または、テスト クラスの前に次の注釈を含めて、テスト内のコンテキストを「手動で」ロードする必要がある場合があります。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")

幸運を!

于 2013-03-08T20:22:56.237 に答える
-1

同じ問題がありましたが、@SpringBootTest のクラスにアドバイザを追加することで解決しました。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyController.class, MyControllerAdvice.class})
@AutoConfigureMockMvc(secure = false)
@ContextConfiguration(classes = {MyTestConfig.class})
@EnableWebMvc
于 2021-09-17T12:51:46.543 に答える