java 单元测试中的 Spring Boot 数据源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49559185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 10:23:45  来源:igfitidea点击:

Spring Boot Datasource in unit tests

javaspringunit-testingspring-bootmockito

提问by Evgeni Dimitrov

I have a simple Spring Boot web app, that reads from a database and return a JSON response. I have the following test configuration:

我有一个简单的 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
}

I have a DataSource bean that is configured in the main configuration of the application. When I run the tests Spring tries to load the context and fails, because the datasource is taken from JNDI. In general I want to avoid creating a datasource for this tests, because I have the repositories mocked.

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

Is it possible to skip the creation of datasource when running the unit tests?

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

In memory database for testing is not an option, because my database creation script has a specific structure and cannot be easily executed from classpath:schema.sql

用于测试的内存数据库不是一种选择,因为我的数据库创建脚本具有特定的结构并且无法从 classpath:schema.sql 轻松执行

EditThe datasource is defined in MyApplication.class

编辑数据源定义在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;
   }

回答by Mayur

Since you are loading configuration class MyApplication.classdatasource bean will be created, Try moving datasource in another bean which is not used in a test, make sure all classes loaded for tests are not dependant on datasource.
Or
In your tests create a config class marked with @TestConfigurationand include it in SpringBootTest(classes=TestConfig.class)mocking data source there like

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

@Bean
public DataSource dataSource() {
    return Mockito.mock(DataSource.class);
}

But this may fail since method call to this mocked datasouce for connection will return null, In that case, you'll have to create an in-memory datasource and then mock jdbcTemplate and rest of dependencies.

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

回答by wjans

Try adding your datasource as a @MockBeantoo:

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

@MockBean
private DataSource dataSource

That way Spring will do the replacing logic for you, having the advantage that your production code bean creation won't even be executed (no JNDI lookup).

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