Java Spring Boot:预加载数据并为测试配置H2。特殊配置问题

Java Spring Boot:预加载数据并为测试配置H2。特殊配置问题,java,spring-boot,testing,junit,h2,Java,Spring Boot,Testing,Junit,H2,我正在开发一个演示spring引导应用程序,其中可以使用应用程序的application.properties使用DDBBconfig类配置3个不同的数据库。 该类包含以下内容: @Configuration public class DDBBConfig { //Flags Configuration @Value("${DDBB.postgresql}") private Boolean postgresql; @Value("${DDBB.mysql}

我正在开发一个演示spring引导应用程序,其中可以使用应用程序的application.properties使用DDBBconfig类配置3个不同的数据库。 该类包含以下内容:

@Configuration
public class DDBBConfig {

    //Flags Configuration

    @Value("${DDBB.postgresql}")
    private Boolean postgresql;

    @Value("${DDBB.mysql}")
    private Boolean mysql;

    @Value("${DDBB.h2}")
    private Boolean h2;


    //Datasource Configuration parameters

    @Value("${mysql.datasource.driver-class-name}")
    private String driverMysql;

    @Value("${mysql.datasource.url}")
    private String urlMysql;

    @Value("${mysql.datasource.username}")
    private String usernameMysql;

    @Value("${mysql.datasource.password}")
    private String passwordMysql;

    @Value("${postgresql.datasource.driver-class-name}")
    private String driverPostgresql;

    @Value("${postgresql.datasource.url}")
    private String urlPostgresql;

    @Value("${postgresql.datasource.username}")
    private String usernamePostgresql;

    @Value("${postgresql.datasource.password}")
    private String passwordPostgresql;

    @Value("${spring.datasource.driverClassName}")
    private String driverH2;

    @Value("${spring.datasource.url}")
    private String urlH2;

    @Value("${spring.datasource.username}")
    private String usernameH2;

    @Value("${spring.datasource.password}")
    private String passwordH2;

    @Bean
    public DataSource getDataSource() {

        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();

        validateOnlyOneFlag( postgresql, mysql, h2 );

        if (Boolean.TRUE.equals( mysql )) {
            dataSourceBuilder.driverClassName( driverMysql );
            dataSourceBuilder.url( urlMysql );
            dataSourceBuilder.username( usernameMysql );
            dataSourceBuilder.password( passwordMysql );
        } else if (Boolean.TRUE.equals( postgresql )) {
            dataSourceBuilder.driverClassName( driverPostgresql );
            dataSourceBuilder.url( urlPostgresql );
            dataSourceBuilder.username( usernamePostgresql );
            dataSourceBuilder.password( passwordPostgresql );
        } else if (Boolean.TRUE.equals( h2 )) {
            dataSourceBuilder.driverClassName( driverH2 );
            dataSourceBuilder.url( urlH2 );
            dataSourceBuilder.username( usernameH2 );
            dataSourceBuilder.password( passwordH2 );

        }

        return dataSourceBuilder.build();
    }

    public void validateOnlyOneFlag(Boolean postgress, Boolean mySql, Boolean h2) {

        Integer flagsTrue = 0;

        if (postgress) {
            flagsTrue++;
        }
        if (mySql) {
            flagsTrue++;
        }
        if (h2) {
            flagsTrue++;
        }

        if (flagsTrue > 1) {
            throw new IllegalArgumentException( "There is more than One database Flags to True." + "\n\tDDBB.postgresql=" + postgress +
                                 "\n\tDDBB.mysql=" + mySql + "\n\tDDBB.h2=" + h2 );
        } else if (flagsTrue == 0) {
            throw new IllegalArgumentException( "\n\n\tDatabase flags are all false, please set at least one flag to true" );
        }
    }

}
package your.package;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import what.ever.you.need;

@RunWith(SpringRunner.class)
@SpringBootTest
public class YourServiceTestClassName {

    @Autowired
    private DDBBConfig config;

    @Autowired
    private DDBBInitializer initializer;

    @Test
    public void testWhatYouNeed() {
        DateSource ds;
        ds = config.getDateSource();
        // do whatever you need

    }

然后在application.properties中,我有somo标志和配置参数

#BBDD:
DDBB.postgresql=true
DDBB.mysql=false
DDBB.h2=false

#JPA:
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

#Properties mysql
mysql.datasource.url=jdbc:mysql://localhost:3306/myapp?serverTimezone=UTC
mysql.datasource.username=root
mysql.datasource.password=AdminPass123
mysql.datasource.driver-class-name=com.mysql.jdbc.Driver

#Properties postgresql
postgresql.datasource.url=jdbc:postgresql://localhost/petapp
postgresql.datasource.username=postgres
postgresql.datasource.password=1234
postgresql.datasource.driver-class-name=org.postgresql.Driver

#Properties H2
h2.datasource.url=jdbc:h2:mem:petappDB
h2.datasource.username=sa
h2.datasource.password=password
h2.datasource.driverClassName=org.h2.Driver
spring.h2.console.enabled=${DDBB.h2}
它的作品完美,所以我可以配置3个数据库

然后,我还有一个数据库初始化类,它为初始化和前端开发添加了一些初始数据。它初始化角色,创建用于登录的默认管理员用户,等等

@Component
public class DDBBInitializer {

    private static final Logger log = LoggerFactory.getLogger( DDBBInitializer.class );

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OwnerRepository ownerRepository;

    @Autowired
    private PetRepository petRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Value("${pettapp.config.default.username}")
    private String defaultUsername;

    @Value("${pettapp.config.default.email}")
    private String defaultEmail;

    @Value("${pettapp.config.default.password}")
    private String defaultPassword;

    @PostConstruct
    private void init() {

        log.info( "Initializacion of the DDBB" );

        for (Roles role : Roles.values()) {
            Role roleEntity = new Role( role );
            roleRepository.save( roleEntity );
            log.info( "Role: " + roleEntity.getRoleName() + " stored on DDBB" );
        }

        User defaultAdminUser = new User();
        defaultAdminUser.setUserId( new BigDecimal( 1 ) );
        defaultAdminUser.addOneRole( Roles.ADMIN );
        defaultAdminUser.setUsername( defaultUsername );
        defaultAdminUser.setPassword( passwordEncoder.encode( defaultPassword ) );
        defaultAdminUser.setActive( true );
        defaultAdminUser.setEmail( defaultEmail );

        log.info( "Default AdminUser Created: " + defaultAdminUser.getUsername() + "/" + defaultPassword );

        Owner adminOwnerProfile = new Owner();
        adminOwnerProfile.setAddress( "Calle de jacinto Nº6 Bajo B" );
        adminOwnerProfile.setName( "Manolo" );
        adminOwnerProfile.setSurname( "Amelgas" );
        adminOwnerProfile.setDefaulter( false );
        adminOwnerProfile.setTelephoneNumber( "678987656 " );
        adminOwnerProfile.setUser( defaultAdminUser );

        defaultAdminUser.setOwner( adminOwnerProfile );

        log.info( "Default Owner Created: " + adminOwnerProfile.getName() + " " + adminOwnerProfile.getSurname() );

        Pet testPet = new Pet();
        testPet.setAlive( true );
        testPet.setBitrh( new Date() );
        testPet.setBreed( "Carlino" );
        testPet.setFur( "White" );
        testPet.setName( "Lucky" );
        testPet.setOwner( adminOwnerProfile );

        adminOwnerProfile.addPet( testPet );

        log.info( "Default Pet Created: " + testPet.getName() );

        userRepository.save( defaultAdminUser );

    }
}
现在我想用Junit为我的应用程序中的所有方法创建所有测试(目前我有10个控制器、15个服务和30个不同的测试方法) 我想将测试配置为始终使用H2数据库并加载一些初始数据,但我找不到关于它的好文档。我应该如何像加载应用程序一样加载初始数据,但只加载测试数据

我创建了一个/test/resources/application-test.properties,其参数与/java/resources/application.properties中的参数相同,但配置了H2(这意味着H”标志设置为true)

编译应用程序时,它仍在使用application.properties文件进行测试,如日志中所示:

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mashosoft.backEndTest.BackEndTestApplicationTests
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mashosoft.backEndTest.BackEndTestApplicationTests
12:01:02.759 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:02.768 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
12:01:02.783 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
12:01:02.824 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
12:01:02.864 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests], using SpringBootContextLoader
12:01:02.869 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: class path resource [com/mashosoft/backEndTest/BackEndTestApplicationTests-context.xml] does not exist
12:01:02.870 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: class path resource [com/mashosoft/backEndTest/BackEndTestApplicationTestsContext.groovy] does not exist
12:01:02.870 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: no resource found for suffixes {-context.xml, Context.groovy}.
12:01:02.872 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: BackEndTestApplicationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
12:01:02.961 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.068 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [D:\Proyectos\PetApp\Back\target\classes\com\mashosoft\backEndTest\BackEndTestApplication.class]
12:01:03.084 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.mashosoft.backEndTest.BackEndTestApplication for test class com.mashosoft.backEndTest.BackEndTestApplicationTests
12:01:03.203 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]: using defaults.
12:01:03.203 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.security.test.context.support.ReactorContextTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
12:01:03.223 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@7d20d0b, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@77f1baf5, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@41a2befb, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@6c40365c, org.springframework.test.context.support.DirtiesContextTestExecutionListener@7bedc48a, org.springframework.test.context.transaction.TransactionalTestExecutionListener@131ef10, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@55b0dcab, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener@38afe297, org.springframework.security.test.context.support.ReactorContextTestExecutionListener@2df3b89c, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@23348b5d, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@70325e14, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@37ceb1df, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@7c9d8e2, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@20d525]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.223 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.239 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@75db5df9 testClass = BackEndTestApplicationTests, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@707194ba testClass = BackEndTestApplicationTests, locations = '{}', classes = '{class com.mashosoft.backEndTest.BackEndTestApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@b9afc07, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@80169cf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@6c9f5c0d, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@1ee807c6], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null].
12:01:03.239 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.239 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.mashosoft.backEndTest.BackEndTestApplicationTests]
12:01:03.270 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
###########################################################
MyAPP BANNER
###########################################################

2019-10-16 12:01:04,040 INFO  [main] org.springframework.boot.StartupInfoLogger: Starting BackEndTestApplicationTests on gggarrido10 with PID 5252 (started by gggarrido in D:\Proyectos\PetApp\Back)
2019-10-16 12:01:04,040 DEBUG [main] org.springframework.boot.StartupInfoLogger: Running with Spring Boot v2.1.6.RELEASE, Spring v5.1.8.RELEASE
2019-10-16 12:01:04,040 INFO  [main] org.springframework.boot.SpringApplication: No active profile set, falling back to default profiles: default
2019-10-16 12:01:07,437 INFO  [main] com.mashosoft.backEndTest.config.DDBB.DDBBConfig: POSTGRESQL DDBB selected
可以看出,for-test仍然在配置postgresql而不是H2 我现在已经知道如何进行了


如果我正确理解了您的问题,您会询问在测试中使用DDBBConfig类(作为bean或初始化为局部变量)时是否将使用application-test.properties或application.properties。答案是它将使用application-test.properties。 重要的是要知道application-test.properties将完全替换application.properties。您不能在application-test.properties中仅定义修改的增量-您必须复制原始文件并对其进行修改

您的测试应该如下所示:

@Configuration
public class DDBBConfig {

    //Flags Configuration

    @Value("${DDBB.postgresql}")
    private Boolean postgresql;

    @Value("${DDBB.mysql}")
    private Boolean mysql;

    @Value("${DDBB.h2}")
    private Boolean h2;


    //Datasource Configuration parameters

    @Value("${mysql.datasource.driver-class-name}")
    private String driverMysql;

    @Value("${mysql.datasource.url}")
    private String urlMysql;

    @Value("${mysql.datasource.username}")
    private String usernameMysql;

    @Value("${mysql.datasource.password}")
    private String passwordMysql;

    @Value("${postgresql.datasource.driver-class-name}")
    private String driverPostgresql;

    @Value("${postgresql.datasource.url}")
    private String urlPostgresql;

    @Value("${postgresql.datasource.username}")
    private String usernamePostgresql;

    @Value("${postgresql.datasource.password}")
    private String passwordPostgresql;

    @Value("${spring.datasource.driverClassName}")
    private String driverH2;

    @Value("${spring.datasource.url}")
    private String urlH2;

    @Value("${spring.datasource.username}")
    private String usernameH2;

    @Value("${spring.datasource.password}")
    private String passwordH2;

    @Bean
    public DataSource getDataSource() {

        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();

        validateOnlyOneFlag( postgresql, mysql, h2 );

        if (Boolean.TRUE.equals( mysql )) {
            dataSourceBuilder.driverClassName( driverMysql );
            dataSourceBuilder.url( urlMysql );
            dataSourceBuilder.username( usernameMysql );
            dataSourceBuilder.password( passwordMysql );
        } else if (Boolean.TRUE.equals( postgresql )) {
            dataSourceBuilder.driverClassName( driverPostgresql );
            dataSourceBuilder.url( urlPostgresql );
            dataSourceBuilder.username( usernamePostgresql );
            dataSourceBuilder.password( passwordPostgresql );
        } else if (Boolean.TRUE.equals( h2 )) {
            dataSourceBuilder.driverClassName( driverH2 );
            dataSourceBuilder.url( urlH2 );
            dataSourceBuilder.username( usernameH2 );
            dataSourceBuilder.password( passwordH2 );

        }

        return dataSourceBuilder.build();
    }

    public void validateOnlyOneFlag(Boolean postgress, Boolean mySql, Boolean h2) {

        Integer flagsTrue = 0;

        if (postgress) {
            flagsTrue++;
        }
        if (mySql) {
            flagsTrue++;
        }
        if (h2) {
            flagsTrue++;
        }

        if (flagsTrue > 1) {
            throw new IllegalArgumentException( "There is more than One database Flags to True." + "\n\tDDBB.postgresql=" + postgress +
                                 "\n\tDDBB.mysql=" + mySql + "\n\tDDBB.h2=" + h2 );
        } else if (flagsTrue == 0) {
            throw new IllegalArgumentException( "\n\n\tDatabase flags are all false, please set at least one flag to true" );
        }
    }

}
package your.package;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import what.ever.you.need;

@RunWith(SpringRunner.class)
@SpringBootTest
public class YourServiceTestClassName {

    @Autowired
    private DDBBConfig config;

    @Autowired
    private DDBBInitializer initializer;

    @Test
    public void testWhatYouNeed() {
        DateSource ds;
        ds = config.getDateSource();
        // do whatever you need

    }


您好,先生。可能是因为我的英语,我的问题没有定义。在一个只有一个数据库配置的应用程序中,我知道我可以创建两个不同的属性文件,一个用于测试,另一个用于普通应用程序。重点是在这种情况下,数据库是通过DDBBconfiguration类配置的,所以如果我使用相同的应用程序结构在.properties for test properties上,我必须首先调用DDBBconfiguration类来配置DDBB for test,我不知道如何调用它firstGabriel,请将/test/resources/application-test.properties重命名为/test/resources/application.properties