Unit Test For Hibernate In Spring Boot

Springframework guru has some nice tutorials showing how to configure spring boot for hibernate JPA and setup junit to do integration test. Here’s how to enable junit testing for hibernate in spring boot.

Tools:
1. JDK1.8
2. spring boot 1.5.6.RELEASE

The setup is using JPA repositories patterns (instead of DAO patterns, in order to reduce line of codes).

1. Referring to spring-guru’s setup, please use spring initializer to get started with spring project. One gradle build file that I’m using is following, and it might be a good starting point:

buildscript {
    ext {
        springBootVersion = '1.5.6.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

//https://stackoverflow.com/questions/23984009/disable-logback-in-springboot/43566507
configurations {
    //all*.exclude module : 'spring-boot-starter-logging'
    //log4j libraries will need to exclude logback
//    all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    all*.exclude group: 'org.springframework.boot', module: 'logback-classic'
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')


    //database using h2
    compile('com.h2database:h2')
    //include spring-shell
    //trying to get both boot and shell working: https://comsysto.com/blog-post/spring-shell
    compile('org.springframework.shell:spring-shell:1.2.0.RELEASE')
    //compile('org.mvnsearch.spring.boot:spring-boot-starter-shell:1.0.0-SNAPSHOT')

    //enable guava
    compile("com.google.guava:guava:22.0")

    //enable joda
    compile("joda-time:joda-time:2.9.9")

    //mds: yahoo-finance-api
    compile("com.yahoofinance-api:YahooFinanceAPI:3.9.0")

    //enable junit
    compile("junit:junit:4.12")
    compile("org.hamcrest:java-hamcrest:2.0.0.0")

    //add sl4j
    compile("org.slf4j:slf4j-api:1.7.21")

    //https://www.slf4j.org/manual.html
    ///////////////////////////////////////////////////////////
    //slf4j -> log4j bridge
    //compile("org.slf4j:slf4j-log4j12:1.8.0-alpha2") //this is working, as recommented by slf4j.org
    compile("org.apache.logging.log4j:log4j-slf4j-impl:2.7+")
    //log4j dependencies  
    compile("org.apache.logging.log4j:log4j-api:2.7+")
    compile("org.apache.logging.log4j:log4j-core:2.7+")
    compile("org.apache.logging.log4j:log4j-jcl:2.7+")
    
    //html parser, for download and scraper
    compile("org.jsoup:jsoup:1.10.3")
    compile("org.apache.httpcomponents:httpclient:4.5.3")

    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('org.springframework.security:spring-security-test')
}

3. Project folder structures are readily defined by Spring Initializer. Add some codes for fun, by following spring-guru’s tutorial. I like the design concept that he’s using.
3.1 main application: main application from spring boot will be annotated as “@SpringBootApplication”, which is the entry point for spring container. All subpackages will be automatically scanned for entities/components/services.
3.2 domain objects: spring data will pickup the entity definitions and mappings.
3.3 repositories: spring data will inject implementations for CRUD operations to the repositories automatically. you just need to define interfaces, and no need to create sql, nor write any codes at all, because spring data has already done that for you.
3.4 services: to gain access objects, which provides a layer of abstraction. so the services defined by interfaces would not concern on the underlying implementation, and doesn’t care whether repository patter is used to provide the service, or DAO pattern is used, or jdbc or any other technologies is used. We just inject the interface whenever we need to access the data.
3.5 configurations: wires up the necessary beans and configurations.
3.6 bootstrapper: provides default initialization for data or anything that’s required to initialization.

4. Configuration file should scan for entity, jpaRepository, and components. Configuration file can manually inject beans to containers via @Bean annotations.

@Configuration
@EnableAutoConfiguration
@EntityScan(basePackages={"com.mm.xshell.xshellboot.domain"})
@EnableJpaRepositories(basePackages={"com.mm.xshell.xshellboot.repositories"})
@ComponentScan(basePackages={"com.mm.xshell.xshellboot.bootstrap"})
public class ProductServiceTestConfig {
/*	@Bean
	ProductRepository productRepository(){
		return new ProductRepositoryTestStub();
	}
*/
	@Bean
	ProductService productService(){
		return new ProductServiceImpl();
	}
}

5. Use annotation @RunWith to start test running using SpringJunit4ClassRunner so that we will have a spring container; and @ContextConfiguration annotation will configure the container with what we defined in 1).

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ProductServiceTestConfig.class})
public class ProductServiceIT {
	private ProductService productService;

	@Autowired
	public void setProductService(ProductService productService){
		this.productService = productService;
	}

	@Test
	public void testGetProduct(){
		Product product = productService.getProductById(1);
		assertEquals("Spring Framework Guru Shirt", product.getDescription());
	}
}

6. Then we can run tests on the domain objects.

Reference:
1. spring boot and spring data jpa
https://springframework.guru/spring-boot-web-application-part-3-spring-data-jpa/
2. spring jpa with junit
https://springframework.guru/integration-testing-with-spring-and-junit/

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s