web-dev-qa-db-ja.com

@WebMvcTestで「少なくとも1つのJPAメタモデルが必要」を取得する

@Controllerのいくつかの基本的な統合テストをしようとしています。

@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
    @Autowired
    private MockMvc mvc;

    @MockBean
    private DemoService demoService;

    @Test
    public void index_shouldBeSuccessful() throws Exception {
        mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
    }
}

しかし、私は得ています

 Java.lang.IllegalStateException:ApplicationContextのロードに失敗しました
原因:org.springframework.beans.factory.BeanCreationException: 'jpaMappingContext'という名前のBeanの作成エラー:initメソッドの呼び出しに失敗しました。ネストされた例外はJava.lang.IllegalArgumentException:少なくとも1つのJPAメタモデルが存在する必要があります!
原因:Java.lang.IllegalArgumentException:少なくとも1つのJPAメタモデルが存在する必要があります!

このエラーを投稿するほとんどの人とは異なり、JPAは使用したくないこのため。 @WebMvcTestを誤って使用しようとしていますか? JPAをこのパーティーに招待しているSpringマジックを追跡するにはどうすればよいですか?

20
Brad Mace

代わりにSpringBootApplicationクラスから@EnableJpaRepositoriesまたは@EntityScanを削除してください:

package com.tdk;

@SpringBootApplication
@Import({ApplicationConfig.class })
public class TdkApplication {

    public static void main(String[] args) {
        SpringApplication.run(TdkApplication.class, args);
    }
}

そして、それを別の設定クラスに入れます:

package com.tdk.config;

@Configuration
@EnableJpaRepositories(basePackages = "com.tdk.repositories")
@EntityScan(basePackages = "com.tdk.domain")
@EnableTransactionManagement
public class ApplicationConfig {

}

そして、ここでテスト:

@RunWith(SpringRunner.class)
@WebAppConfiguration
@WebMvcTest
public class MockMvcTests {

}
14

または、テストケース内でコントローラー(およびその依存関係)のみを含むカスタム構成クラスを定義して、Springでthisコンテキストを強制的に使用することもできます。
注釈付きのMockMvcであれば、テストケースでWebMvcTestおよびその他の優れた機能にアクセスできます。

@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
    @Autowired
    private MockMvc mvc;

    @MockBean
    private DemoService demoService;

    @Test
    public void index_shouldBeSuccessful() throws Exception {
        mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
    }

    @Configuration
    @ComponentScan(basePackageClasses = { DemoController.class })
    public static class TestConf {}
5
Mohnish

同じ問題がありました。 @WebMvcTestは、@ SpringBootApplicationアノテーションが付けられたクラスを探します(見つからない場合は、アプリ構造の同じディレクトリ以上にあります)。これがどのように機能するかを読むことができます@ https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured- mvc-tests

@SpringBootApplicationアノテーションが付けられたクラスに@EntityScan/@ EnableJpaRepositoriesも含まれている場合、このエラーが発生します。 @SpringBootApplicationでこれらの注釈があり、サービスをモックしているため(実際にはJPAを使用していないため)。私は最もきれいではないかもしれないが、私のために働く回避策を見つけました。

このクラスをテストディレクトリ(ルート)に配置します。 @WebMvcTestは、実際のApplicationクラスの前にこのクラスを見つけます。このクラスでは、@ EnableJpaRepositories/@ EntityScanを追加する必要はありません。

@SpringBootApplication(scanBasePackageClasses = {
    xxx.service.PackageMarker.class,
    xxx.web.PackageMarker.class
})
public class Application {
}

そして、テストは同じように見えます。

@RunWith(SpringRunner.class)
@WebMvcTest
@WithMockUser
public class ControllerIT {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Service service;

    @Test
    public void testName() throws Exception {
        // when(service.xxx(any(xxx.class))).thenReturn(xxx); 
        // mockMvc.perform(post("/api/xxx")...
        // some assertions
    }
}

お役に立てれば!

5
Justin K

誰かがSpringブートを使用しており、@EntityScanおよび@EnableJpaRepositoriesを削除したくない場合は、テストクラスから@WebMvcTest注釈を削除し、代わりに次を追加できます。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class DemoControllerIntegrationTests {
    @Autowired
    private MockMvc mvc;

    //...
}

MockMvcを自動配線して使用できるようになります。

2
Mis94

クラスDemoControllerIntegrationTestsの上に@MockBean(JpaMetamodelMappingContext.class)を追加します。

@RunWith(SpringRunner.class)
@WebMvcTest(DemoController.class)
@MockBean(JpaMetamodelMappingContext.class)
public class DemoControllerIntegrationTests {
    ...
}

テストでデータベースを使用していないため、Springはこの例外をスローします。 JpaMetamodelMappingContextクラスをモックすることにより、必要なメタモデルをバイパスします。

1
youhans