アプリケーションにコントローラーのセットと、これらのコントローラーのそれぞれで使用される特定のデータ要素を設定する@ControllerAdvice
として注釈が付けられたクラスがあります。私はSpring MVC 3.2
を使用しており、これらのコントローラーにJunitsを使用しています。 Junitを実行すると、コントロールはControllerAdvice
クラスに移動しません。そこで、アプリをTomcat
にデプロイし、ブラウザー経由でリクエストを送信すると正常に動作します。
ご意見をお聞かせください。
@ eugene-toおよび他の同様の回答を使用した後、 here Springで制限を見つけ、問題を提起しました: https://jira.spring.io/browse/SPR-12751
その結果、Springテストでは、4.2でビルダーに_@ControllerAdvice
_クラスを登録する機能が導入されました。 Spring Bootを使用している場合は、1.3.0以降が必要です。
この改善により、スタンドアロンセットアップを使用している場合、1つ以上のControllerAdvice
インスタンスを次のように設定できます。
_mockMvc = MockMvcBuilders.standaloneSetup(yourController)
.setControllerAdvice(new YourControllerAdvice())
.build();
_
注:名前setControllerAdvice()
はすぐにはわかりませんが、var-を持っているため、多くのインスタンスを渡すことができますargs署名。
@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;
}
@ControllerAdvice
アノテーションが付けられたExceptionHandler
をテストしようとすると、同様の問題が発生しました。私の場合、テストクラスの@Configuration
に@EnableWebMvc
注釈付きの@ContextConfiguration
ファイルを追加する必要がありました。
したがって、私のテストは次のようになりました。
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
RestProcessingExceptionHandler.class,
TestConfiguration.class,
RestProcessingExceptionThrowingController.class })
public class TestRestProcessingExceptionHandler {
private MockMvc mockMvc;
@Autowired
WebApplicationContext wac;
@Before
public void setup() {
mockMvc = webAppContextSetup(wac).build();
}
@Configuration
// !!! this is very important - conf with this annotation
// must be included in @ContextConfiguration
@EnableWebMvc
public static class TestConfiguration { }
@Controller
@RequestMapping("/tests")
public static class RestProcessingExceptionThrowingController {
@RequestMapping(value = "/exception", method = GET)
public @ResponseBody String find() {
throw new RestProcessingException("global_error_test");
}
}
@Test
public void testHandleException() throws Exception {
mockMvc.perform(get("/tests/exception"))
.andExpect(new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
result.getResponse().getContentAsString().contains("global_error_test");
}
})
.andExpect(status().isBadRequest());
}
}
@EnableWebMvc
構成でテストに合格しました。
これは私のために働いています
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)).andReturn();
}
}
私はかなり長い間、同じことで苦労してきました。掘り下げた後、最良のリファレンスはSpringのドキュメントでした:
要するに、コントローラーとそのメソッドを単純にテストする場合、 'standaloneSetup'メソッドを使用して、簡単なSpring MVC構成を作成できます。これには、notに@ControllerAdviceで注釈を付けたエラーハンドラが含まれます。
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
}
// ...
doesがエラーハンドラを含む、より完全な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;
// ...
}
@tunguskiサンプルコードは機能しますが、物事がどのように機能するかを理解することは有益です。これは、物事を設定する1つの方法にすぎません。
@EnableWebMvc
は、Spring構成ファイルの次のコマンドと同等です。
<mvc:annotation-driven />
基本的に動作するためには、Spring Mvcを初期化し、すべてのコントローラーとBean参照をロードする必要があります。したがって、以下は有効なセットアップである可能性があります
以下は、テストクラスを設定する方法です。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath: "classpath:test-context.xml" })
@WebAppConfiguration
public class BaseTest {
@Autowired
WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
そして、次はテスト用のスプリング構成です
<mvc:annotation-driven />
<context:component-scan base-package="com.base.package.controllers" />
spock (groovy)を使用してコントローラーテストを作成しているときに、この問題が発生しました。私のテストクラスはもともと次のように書かれていました。
@AutoConfigureMockMvc(secure = false)
@SpringBootTest
@Category(RestTest)
class FooControllerTest extends Specification {
def fooService = Mock(FooService)
def underTest = new FooController(FooService)
def mockMvc = MockMvcBuilders.standaloneSetup(underTest).build()
....
}
これにより、ControllerAdviceが無視されました。コードをモックを自動配線するように変更すると、問題が修正されました。
@AutoConfigureMockMvc(secure = false)
@SpringBootTest
@Category(RestTest)
class FooControllerTest extends Specification {
@AutowiredMock
FooService FooService
@Autowired
MockMvc mockMvc
テストでasyncDispatchを使用する必要があると思います。非同期コントローラーでは、通常のテストフレームワークが壊れています。
特定の回答を期待する前に、より多くの情報と、おそらく実際のコードや設定ファイルを提供する必要があります。とは言っても、提供された小さな情報に基づいて、注釈付きBeanがロードされていないように聞こえます。
テストapplicationContext.xml(または、使用している場合は同等のspring configファイル)に次を追加してみてください。
<context:component-scan base-package="com.example.path.to.package" />
または、テストクラスの前に次の注釈を含めることにより、テスト内でコンテキストを「手動で」ロードする必要がある場合があります。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
がんばろう!