Java Spring Boot单元测试-测试失败,抱怨没有;“实体管理工厂”;bean定义

Java Spring Boot单元测试-测试失败,抱怨没有;“实体管理工厂”;bean定义,java,unit-testing,spring-mvc,spring-boot,mockito,Java,Unit Testing,Spring Mvc,Spring Boot,Mockito,我正在尝试为Spring引导应用程序中的控制器编写一个单元测试。应用程序运行平稳,我的问题是运行它的测试 以下是测试代码: @RunWith(SpringRunner.class) @WebMvcTest(MyController.class) @AutoConfigureTestEntityManager public class MyControllerTest { @Autowired private MockMvc mockMvc; @Mock private MyRepositor

我正在尝试为Spring引导应用程序中的控制器编写一个单元测试。应用程序运行平稳,我的问题是运行它的测试

以下是测试代码:

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
@AutoConfigureTestEntityManager
public class MyControllerTest {

@Autowired
private MockMvc mockMvc;

@Mock
private MyRepository myRepository;

@Mock
ZendeskNotifier zendeskNotifier;

@Mock
ActivityLogger activityLogger;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

@Test
public void cannotSendFooWithoutMessageBody() throws Exception {
    this.mockMvc.perform(post("/api/v1/foo/1/send"))
            .andDo(print())
            .andExpect(status().is4xxClientError())
            .andExpect(content().string(containsString("The message body cannot be empty.")));
}
}
当我尝试运行它时,我得到:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field jobEventRepository in foo.bar.util.memsource.svc.MemsourceEventProcessor required a bean named 'entityManagerFactory' that could not be found.


Action:

Consider defining a bean named 'entityManagerFactory' in your configuration.

这让我觉得很奇怪,因为我提供了
自动配置EntityManager
注释,并且希望所有与
EntityManager
相关的东西都准备就绪。

您需要配置
EntityManager工厂
,您可以参考下面的代码

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="org.demo.test.entity" />
<property name="dataSource" ref="dataSource" />

<property name="jpaProperties">
    <props>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.hbm2ddl.auto">create</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    </props>
</property>

<property name="persistenceProvider">
    <bean class="org.hibernate.jpa.HibernatePersistenceProvider">
</bean>
</property>

</bean>

真的
创造
org.hibernate.dialogue.mysqldialogue

mockito
测试类中注入Spring的
TestEntityManager

@Autowired
private TestEntityManager entityManager;

您已经在测试类上使用
@autoconfiguretestentymanager
自动配置此测试实体管理器。因此,您不必在配置文件中执行任何其他操作。

如果Google将您带到这里,并且您使用的是Spring Boot,那么您可能需要将
@DataJpaTest
添加到测试类中。可以在
org.springframework.boot:springboot-test-autoconfigure
中找到它。重新运行时,您可能还发现需要声明对
org的依赖关系。hibernate:hibernate validator

Spring Boot正在加载应用程序的配置,导致数据层被初始化

摘自Spring Boot的文档:

Spring Boot的@*测试注释搜索您的主配置 当您没有明确定义一个时自动

搜索算法从包含测试的包开始工作 直到找到一个用@SpringBootApplication或 @SpringBoot配置。只要您在 明智的做法是,通常可以找到您的主配置

当扫描点击您的
main
类时,可能会发现类似
@EnableJpaRepositories
的注释,该注释会初始化您的数据层,因此需要实体管理器工厂。(您也可能会看到其他副作用,如Hibernate在应用程序使用内存数据库时初始化内存数据库。)

正如其他答案所建议的,您可以初始化数据层,或者尝试连接/模拟缺少的bean。但是,由于您没有在这里测试数据层,因此最好控制测试的配置

文件提出了一些解决方案:

  • @EnableJpaRepositories
    从主类移动到子包中的配置类。它将被应用程序扫描(从上到下),但不会被单元测试扫描。本节将对此进行讨论

  • 添加嵌套的
    @Configuration
    类以覆盖单元测试使用的配置


  • 一般来说,第一条似乎是一条很好的规则。其他注释,如
    @EnableBatchProcessing
    @EnableScheduling
    可以以相同的方式处理,这将加快单元测试的速度。

    我尝试了自动连接
    TestEntityManager
    EntityManagerFactory
    ,得到了与上述完全相同的结果:(嗨,阿尔瓦罗,你最终解决了这个问题吗?谢谢。嗨@Daniel,事实上,没有。):(我已经离开了那份工作,据我所知,他们从来没有成功过(反正他们从来没有真正进入过TDD船)但为什么我需要将@DataJpaTest添加到控制器测试中?我已经用完全空的测试创建了完全空的控制器,但仍然失败,出现“NoSuchBeanDefinitionException:没有名为“entityManagerFactory”的bean可用。为什么(编辑:另外,您不能同时拥有\@WebMvcTest和\@DataJpaTest。@Dalibor感谢您对空测试的评论-它帮助我找到了答案,即您的应用程序配置(和我的配置)正在被单元测试发现和使用。我发布了一个答案,并给出了完整的解释和修复方法。请注意,如果您将@EnableJpaRepositories移动到配置类,则在运行应用程序时可能会遇到另一个问题,而应用程序是您的存储库,而不是自动连接。解决方案如下: