单元测试中的Spring Boot数据源

Evg*_*rov 5 java spring unit-testing mockito spring-boot

我有一个简单的Spring Boot Web应用程序,它从数据库中读取并返回JSON响应.我有以下测试配置:

@RunWith(SpringRunner.class)
@SpringBootTest(classes=MyApplication.class, properties={"spring.config.name=myapp"})
@AutoConfigureMockMvc
public class ControllerTests {
    @Autowired
    private MockMvc mvc;
    @MockBean
    private ProductRepository productRepo;
    @MockBean
    private MonitorRepository monitorRepo;

    @Before
    public void setupMock() {
        Mockito.when(productRepo.findProducts(anyString(), anyString()))
        .thenReturn(Arrays.asList(dummyProduct()));     
    }

    @Test
    public void expectBadRequestWhenNoParamters() throws Exception {    
        mvc.perform(get("/products"))
                .andExpect(status().is(400))
                .andExpect(jsonPath("$.advice.status", is("ERROR")));
    }

    //other tests
}
Run Code Online (Sandbox Code Playgroud)

我有一个在应用程序的主配置中配置的DataSource bean.当我运行测试时,Spring尝试加载上下文并失败,因为数据源来自JNDI.一般情况下,我想避免为此测试创建数据源,因为我已经模拟了存储库.

在运行单元测试时是否可以跳过数据源的创建?

在内存数据库中进行测试不是一个选项,因为我的数据库创建脚本具有特定的结构,并且无法从类路径中轻松执行:schema.sql

编辑 数据源定义于MyApplication.class

    @Bean
    DataSource dataSource(DatabaseProeprties databaseProps) throws NamingException {
       DataSource dataSource = null;
       JndiTemplate jndi = new JndiTemplate();
       setJndiEnvironment(databaseProps, jndi);
       try {
           dataSource = jndi.lookup(databaseProps.getName(), DataSource.class);
       } catch (NamingException e) {
           logger.error("Exception loading JNDI datasource", e);
           throw e;
       }
       return dataSource;
   }
Run Code Online (Sandbox Code Playgroud)

May*_*yur 7

由于您正在加载配置类,MyApplication.class因此将创建数据源bean,尝试在另一个未在测试中使用的bean中移动数据源,确保为测试加载的所有类都不依赖于数据源.
或者
在您的测试中创建一个标记的配置类,@TestConfiguration并将其包含在SpringBootTest(classes=TestConfig.class)那里的模拟数据源中

@Bean
public DataSource dataSource() {
    return Mockito.mock(DataSource.class);
}
Run Code Online (Sandbox Code Playgroud)

但是这可能会失败,因为对此连接的模拟数据的方法调用将返回null,在这种情况下,您将必须创建内存中的数据源,然后模拟jdbcTemplate和其余的依赖项.

  • 您好,在尝试您的解决方案后,在我的情况下,我收到错误“BeanCreationException:创建类路径资源中定义的名为“entityManagerFactory”的bean时出错”[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]:调用init方法失败;嵌套异常是 org.hibernate.service.spi.ServiceException: 无法创建请求的服务 [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]` 您有什么想法吗? (3认同)

wja*_*ans 6

尝试将您的数据源添加为@MockBean

@MockBean
private DataSource dataSource
Run Code Online (Sandbox Code Playgroud)

这样 Spring 将为您执行替换逻辑,其优势在于您的生产代码 bean 创建甚至不会被执行(没有 JNDI 查找)。

  • 这也是我的做法。您可以将 MockBean 添加到“TestConfig.class”中,以最大限度地减少代码重复。 (2认同)