mercredi 16 octobre 2019

Spring Boot: Preload Data and configure H2 for tests. Special Configuration question

I am developing a demo spring boot app in which it is possible to configure 3 different database with a DDBBconfig class by usisng application.properties of the aplication. The class iis the following:

@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" );
        }
    }

}

Then in the application.properties I have somo flags and the configuration parameters.

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

#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
spring.datasource.url=jdbc:h2:mem:petappDB
spring.datasource.username=sa
spring.datasource.password=password
spring.datasource.driverClassName=org.h2.Driver
spring.h2.console.enabled=${DDBB.h2}

Its works perfect so I can configure 3 databases.

Then I also have a DataBase initialization class that add some initial data for initialization and front developing reasons. It initialize the roles, creates a default admin user for login and so on.

@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
    PetRepository petRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @PostConstruct
    private void init() {

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

        //TODO: Hacer el usuario y contraseña una property configurable
        User defaultAdminUser = new User();
        defaultAdminUser.setUserId( new BigDecimal( 1 ) );
        defaultAdminUser.addOneRole( Roles.ADMIN );
        defaultAdminUser.setUsername( "AdminRoot" );
        defaultAdminUser.setPassword( passwordEncoder.encode( "AdminPass246" ) );
        defaultAdminUser.setActive( true );
        defaultAdminUser.setEmail( "rootEmail@root.com" );

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

        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() );

        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 );

        userRepository.save( defaultAdminUser );

    }
}

Now I want to create all Test with Junit for all methods that I have in my application (currently i have like 10 controllers, 15 services and 30 different methods to Test) I would like to configure the test to always use an H2 database and load some initial data and i cant find good documentation about it. How i should proccedd to load initial data as i do for the app but only for the test?.

I have try to create a /test/resources/application-test.properties with the same parameters as in /java/resources/application.properties but configuring H2 but with this properties I should call first the DDBBconfiguration class to configure database and Its a configuration class located in java/src, not in tests folder ¿Should I inject it on test as a bean and configure the database?

I have now idea about how to proceed

all the help you can give me would be appreciated.

Aucun commentaire:

Enregistrer un commentaire