jpa - 对于@SpringBootTest,为什么我被告知 "Configuration error: found multiple declarations of @BootstrapWith",即使我没有一个?

标签 jpa spring-security integration-testing spring-boot-test spring-boot-2

我正在使用 Spring Boot 2.1。我正在尝试设置 Spring Boot 集成测试来测试 Controller 。我有以下内容

@ContextConfiguration(classes=CardmaniaApplication.class)
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
@DataJpaTest
public class CardControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private ICardRepository cardRepository;

    @Autowired
    private IUserRepository userRepository;
    
    @Autowired
    private IOccasionRepository occasionRepository;
    
    @Test
    @WithMockUser(authorities = {"ADMIN"})
    void createCard() throws Exception {
        final Card card = new Card();
        final User author = userRepository.findAll().get(0);
        card.setAuthor(author);
        final Occasion occasion = occasionRepository.findAll().get(0);
        card.setOccasion(occasion);
        byte[] image = new byte[] {1, 1, 1, 1};
        card.setImage(image);
        
        mockMvc.perform(post("/api/cards").contentType("application/json")
                .content(objectMapper.writeValueAsString(card)))
                .andExpect(status().isOk());

        List<Card> cards = cardRepository.findByOccasion(occasion);
        assertThat(cards.size()).isEqualTo(1);
        final Card cardEntity = cards.get(0);
        assertThat(cardEntity.getImage()).isEqualTo(image);
    }
}

我对如何注释主类有点困惑,因为当我运行测试时,我得到了异常

java.lang.IllegalStateException: Configuration error: found multiple declarations of @BootstrapWith for test class [com.burrobuie.cardmania.controller.CardControllerIntegrationTest]: [@org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.context.SpringBootTestContextBootstrapper), @org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper)]
    at org.springframework.test.context.BootstrapUtils.resolveExplicitTestContextBootstrapper(BootstrapUtils.java:166)
    at org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.java:127)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:122)
    at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$0(ExtensionValuesStore.java:81)
    at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:182)
    at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:84)
    at org.junit.jupiter.engine.execution.ExtensionValuesStore.getOrComputeIfAbsent(ExtensionValuesStore.java:88)
    at org.junit.jupiter.engine.execution.NamespaceAwareStore.getOrComputeIfAbsent(NamespaceAwareStore.java:61)
    at org.springframework.test.context.junit.jupiter.SpringExtension.getTestContextManager(SpringExtension.java:213)
    at org.springframework.test.context.junit.jupiter.SpringExtension.beforeAll(SpringExtension.java:77)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$7(ClassBasedTestDescriptor.java:359)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:359)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:189)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:78)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:132)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:141)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
    Suppressed: java.lang.IllegalStateException: Configuration error: found multiple declarations of @BootstrapWith for test class [com.burrobuie.cardmania.controller.CardControllerIntegrationTest]: [@org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.context.SpringBootTestContextBootstrapper), @org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper)]
        at org.springframework.test.context.BootstrapUtils.resolveExplicitTestContextBootstrapper(BootstrapUtils.java:166)
        at org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.java:127)
        at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:122)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$0(ExtensionValuesStore.java:81)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:182)
        at org.junit.jupiter.engine.execution.ExtensionValuesStore.remove(ExtensionValuesStore.java:98)
        at org.junit.jupiter.engine.execution.NamespaceAwareStore.remove(NamespaceAwareStore.java:73)
        at org.springframework.test.context.junit.jupiter.SpringExtension.afterAll(SpringExtension.java:89)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$13(ClassBasedTestDescriptor.java:425)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllCallbacks$14(ClassBasedTestDescriptor.java:425)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeAfterAllCallbacks(ClassBasedTestDescriptor.java:425)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:213)
        at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:78)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:145)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:145)
    

... 29 more

我需要在 header 中添加或删除哪些内容才能运行测试?

我必须包含以下内容,因为 SO 告诉我我的问题主要是代码。 Lorem ipsum dolor sat amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua。 Ut enim ad minim veniam, quis nostrud exeritation ullamco labouris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Exceeur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est labourum.

最佳答案

您有多个相互冲突的测试注释。对于您的用例: Controller 的集成测试,以下设置就足够了:

@SpringBootTest
@AutoConfigureMockMvc
public class CardControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private ICardRepository cardRepository;

    @Autowired
    private IUserRepository userRepository;
    
    @Autowired
    private IOccasionRepository occasionRepository;
    
    @Test
    @WithMockUser(authorities = {"ADMIN"})
    void createCard() throws Exception {
        final Card card = new Card();
        final User author = userRepository.findAll().get(0);
        card.setAuthor(author);
        final Occasion occasion = occasionRepository.findAll().get(0);
        card.setOccasion(occasion);
        byte[] image = new byte[] {1, 1, 1, 1};
        card.setImage(image);
        
        mockMvc.perform(post("/api/cards").contentType("application/json")
                .content(objectMapper.writeValueAsString(card)))
                .andExpect(status().isOk());

        List<Card> cards = cardRepository.findByOccasion(occasion);
        assertThat(cards.size()).isEqualTo(1);
        final Card cardEntity = cards.get(0);
        assertThat(cardEntity.getImage()).isEqualTo(image);
    }
}

说明:

  • @DataJpaTest用于测试与数据库相关的部分 隔离的应用程序(例如存储库)
  • @ExtendWith(SpringExtension.class)是多余的,因为它已经来了 与 @SpringBootTest
  • @ContextConfiguration是多余的,如@SpringBootTest确保 创建你的上下文

通过此设置,您现在可以启动整个 Spring Context(无需嵌入的 servlet 容器),并可以使用 MockMvc 访问您的端点。 。确保您已为集成测试配置了对数据库的访问权限,例如您可以使用Testcontainers为此。

如果您还想启动 Tomcat 并使用例如TestRestTemplateWebTestClient无需 MockMvc 即可访问您的端点,使用以下内容:@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

您始终可以查看注释的源代码,以了解它们将在后台启用什么(例如,在 IDEA 中按 CTRL + 左键单击)。 @SpringBootTest例如,如下所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
public @interface SpringBootTest {

}

关于jpa - 对于@SpringBootTest,为什么我被告知 "Configuration error: found multiple declarations of @BootstrapWith",即使我没有一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62645745/

相关文章:

java - org.hibernate.HibernateException : createQuery is not valid without active transaction @scheduled

spring-security - 如何根据用户角色更改 default-target-url

spring-mvc - 如何对 Spring Controller Advice 进行集成测试

java - EclipseLink JPA : remove and persist in the same transaction, 约束错误

java - 如何将 lombok 和 JPAMetalModel 处理器与 maven 合并

java - 当 url 包含字符串 "?error "时,WebSphere 不显示网页元素

unit-testing - 为什么使用集成测试而不是单元测试是一个坏主意?

java - Maven文件夹布局: Should I place tests in the EAR or its sub-modules?

java - Spring Data - 自定义查询 : count and list

java - PagingAndSortingRepository如何实现PostFilter?