向工作的Spring Boot项目添加依赖项会使所有JUnit

时间:2018-04-11 13:47:17

标签: spring spring-boot

我有2个Eclipse项目,每个项目都有Spring管理的服务。我为每个人使用Spring Boot starter依赖项。每个都可以正常工作,并且可以通过SpringRunner.class@SpringBootTest启动JUnit进行测试。

现在,我想从项目2中的项目1调用一些服务,所以我在项目2的pom.xml中添加了一个依赖项,我添加了 @ComponentScan(basePackages = “com.project1”)

从那时起,我无法启动任何JUnit,它抱怨dataSource没有设置,比如配置随机混合。

我的问题是:当您创建Spring Boot应用程序并且想要在单独的项目中隔离某些功能时(这里是XML功能),建议的做法是什么?如果你不能拥有2个spring boot应用程序,而另一个依赖于另一个,那么你需要的Spring依赖项是什么,所以spring boot项目可以处理非spring spring依赖项,所以你仍然可以在本地使用Spring runner启动JUnit ?

我是否需要逐个选择Spring依赖项(core,bean,context,test,log4j,slf4j,junit,hamcrest,...),就像Spring boot存在之前一样?

请参阅我对可能重复的原因不同的评论。

从我的模块项目中删除所有Spring启动依赖项后,只要添加“ComponentScan”扫描模块服务,我仍然会收到错误。

这是我的数据库配置(主要项目取决于xml模块)要在包配置上清除。在我从模块项目的包中添加ComponentScan之前,此配置完美无缺:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="fr.my.project.repository")
class PersistenceContext {

  private static final String[] ENTITY_PACKAGES = { "fr.my.project.model" };

  private static final String PROP_DB_DRIVER_CLASS = "db.driver";
  private static final String PROP_DB_PASSWORD = "db.password";
  private static final String PROP_DB_URL = "db.url";
  private static final String PROP_DB_USER = "db.username";

  private static final String PROP_HIBERNATE_DIALECT = "hibernate.dialect";
  private static final String PROP_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
  private static final String PROP_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
  private static final String PROP_HIBERNATE_SHOW_SQL = "hibernate.show_sql";

  /**
   * Creates and configures the HikariCP datasource bean.
   * 
   * @param env
   *          The runtime environment of our application.
   * @return
   */
  @Bean(destroyMethod = "close")
  DataSource dataSource(Environment env) {
    HikariConfig dataSourceConfig = new HikariConfig();
    dataSourceConfig.setDriverClassName(env.getRequiredProperty(PROP_DB_DRIVER_CLASS));
    dataSourceConfig.setJdbcUrl(env.getRequiredProperty(PROP_DB_URL));
    dataSourceConfig.setUsername(env.getRequiredProperty(PROP_DB_USER));
    dataSourceConfig.setPassword(env.getRequiredProperty(PROP_DB_PASSWORD));

    return new HikariDataSource(dataSourceConfig);
  }

  /**
   * Creates the bean that creates the JPA entity manager factory.
   * 
   * @param dataSource
   *          The datasource that provides the database connections.
   * @param env
   *          The runtime environment of our application.
   * @return
   */
  @Bean
  LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, Environment env) {
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactoryBean.setDataSource(dataSource);
    entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactoryBean.setPackagesToScan(ENTITY_PACKAGES);

    Properties jpaProperties = new Properties();

    // Configures the used database dialect. This allows Hibernate to create SQL
    // that is optimized for the used database.
    jpaProperties.put(PROP_HIBERNATE_DIALECT, env.getRequiredProperty(PROP_HIBERNATE_DIALECT));

    // Specifies the action that is invoked to the database when the Hibernate
    // SessionFactory is created or closed.
    jpaProperties.put(PROP_HIBERNATE_HBM2DDL_AUTO, env.getRequiredProperty(PROP_HIBERNATE_HBM2DDL_AUTO));

    // If the value of this property is true, Hibernate writes all SQL
    // statements to the console.
    jpaProperties.put(PROP_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROP_HIBERNATE_SHOW_SQL));

    // If the value of this property is true, Hibernate will use prettyprint
    // when it writes SQL to the console.
    jpaProperties.put(PROP_HIBERNATE_FORMAT_SQL, env.getRequiredProperty(PROP_HIBERNATE_FORMAT_SQL));

    entityManagerFactoryBean.setJpaProperties(jpaProperties);

    return entityManagerFactoryBean;
  }

  /**
   * Creates the transaction manager bean that integrates the used JPA provider with the Spring transaction mechanism.
   * 
   * @param entityManagerFactory
   *          The used JPA entity manager factory.
   * @return
   */
  @Bean
  JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
  }
}

并在添加:

之后
@ComponentScan(basePackages="fr.my.module.xml.service")

启动任何Junit时出现此错误:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

2 个答案:

答案 0 :(得分:1)

这是关于如何配置依赖项目的临时答案,但我希望有一些更简单的方法可以使所有应用程序模块的Spring Boot快捷方式受益。

  • 带有手动最小依赖关系的pom.xml:

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.14.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.3.14.RELEASE</version>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.11</version>
    </dependency>
    

手动测试配置:

@RunWith(SpringRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes=AppConfig.class)
public class XmlTest {

手动应用配置:

@Configuration
@ComponentScan(basePackages="my.package.xml")
public class AppConfig {

}

执行所有这些尝试后的Sooooooo,Spring Boot可能根本就不是这个问题的原因。

问题是我正在添加@ComponentScan(basePackages =&#34; fr.package.xml&#34;)希望完成默认的包扫描,但它覆盖了它。

添加软件包的正确方法是在添加新软件包之前明确重新声明默认软件包: @ComponentScan(basePackages = {&#34; fr.package.xml&#34;,&#34; fr.package.persistence&#34;})

答案 1 :(得分:0)

我的另一个答案是关于在Spring Boot应用程序中为模块设置手动最小依赖项。但是这里有一个在模块中使用Spring引导特殊依赖项的例子,它不是主应用程序:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

然后,你没有宣布&#34; @ SpringBootApplication&#34;在src / main / java的主类中,它可能会破坏全局包装,但是你在测试类中进行设置:

@RunWith(SpringRunner.class)
@SpringBootTest("service.message=Hello")
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void contextLoads() {
        assertThat(myService.message()).isNotNull();
    }

    @SpringBootApplication
    static class TestConfiguration {
    }

}

来源:https://github.com/spring-guides/gs-multi-module/tree/master/complete