Loading initial test data in H2 in spring boot - spring-boot

I am using Spring Boot 1.5.8.Release and writing test cases using H2 in memory database. Currently in each test case class, we have #Before annotation, where we insert data using Spring Data classes.
I want to know, can I have a single place in project where we can define data for our all test cases. The database tables are created by Hybernate using entity classes. The only desired thing is about inserting data from single place instead of from #Before in each test case class.
I tried to use data.sql containing Insert statements but with it, Spring does not generate schema objects (tables) due to which I get table not found errors. I do not want to specify Create Table statement for each table in schema.sql
application-test.yml
spring:
datasource:
url: jdbc:h2:mem:test;
driverClassName: org.h2.Driver
username: sa
password:
jpa:
database: h2
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create
naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
properties:
hibernate:
show_sql: true
format_sql: false
Schema.sql
CREATE SCHEMA AB AUTHORIZATION SA;
AbcControllerTest.java
#RunWith(SpringRunner.class)
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
#SpringBootTest(classes = WebApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#ActiveProfiles("test")
public class AbcControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private LeDataService leDataService;
#Before
public void setup() {
MyInfo myInfo = new MyInfo();
..............
..............
leDataService.save(myInfo);
}
#Test
public void getAbcTest() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/Abcs/1234567/12345678")
.with(SecurityMockMvcRequestPostProcessors.user("test").password("test123"))
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isOk())
}
}

create new class annotated with #Component #Profile({ "dev", "test" }) and that implements CommandLineRunner then inject dependencies
Override run() method with your initial data that came with CommandLineRunner
for example
#Component
#Profile({ "dev", "test" })
setupInitialData implements CommandLineRunner {
UserService userService;
//bla bla
#Override
#Transactional
public void run(String... args) {
User user = new User;
user.setName("test");
userService.save(user);
//bla bla
}
}

Related

How to store data to MariaDB at beforeEach method in Spring boot tests?

I cannot write data to db in #beforeEach as lifecycle methods are not transactional. How can I force data to commit? Data is stored in a transaction, but it is executed after the tearDown() method. By the way, I use MariaDB test container.
#SpringBootTest
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ContextConfiguration(initializers = TestConfigurations.Initializer.class,
classes = {Application.class, TestConfigurations.class})
#Transactional(transactionManager = "transactionManager")
public class SomeTest {
#Autowired
private SomeRepository someRepository;
#Nested
class SomeNestedClass {
#BeforeEach
void setUp() {
someRepository.saveAll(Fixtures.getSomeEntities());
}
#AfterEach
public void tearDown() {
someRepository.deleteAll();
}
...
Your test methods annotated with #Transactional will be rollback by default by Spring Test, so you can just initialize your data at the beginning of your test.
try using #BeforeTransaction
/ #AfterTransaction

SpringBoot MockMVC Controller Test with in-memory H2 not creating JPA entities as table or not inserting seed data

Status returns 200 but when i checked the logs cannot see any H2 logs for creating tables or inserting data. So, what do you suggest me to do.
Another thing I want to mention is that while testing the Repository, I was able to do my Repository tests with h2 using the #DataJpaTest annotation. Below you can see my sample properties file and controllertest file.
#RunWith(SpringRunner.class)
#WebMvcTest(VehicleController.class)
#ContextConfiguration(classes=DemoApplication.class)
#AutoConfigureMockMvc
public class VehicleControllerTest {
#Autowired
private WebApplicationContext context;
#Autowired
private MockMvc mvc;
#MockBean
private VehicleService vehicleService;
#Before
public void setup() {
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void RetrieveAllVehicles() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/vehicle").content("application/json");
MvcResult result = this.mvc.perform(requestBuilder).andExpect(status().isOk())
.andReturn();
assertEquals(12 , 12);
}
Application Properties file like that for in memory database with H2.
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.datasource.initialization-mode=always

Spring Boot, H2 and Flyway: run integration tests with two versions of the database

For blue/green deployment, it is required that the new application version run with both the old and the new database version. So my integration tests should run twice: with previous database version (partial migration to version-1) and then with latest version.
I could do this by setting up a local MySQL database and handle the migration and test running manually but I wonder if there is a way to use H2 and automate the process somehow for CI.
I have a very basic Spring Boot/Flyway setup.
application.yaml:
spring:
profiles: db_h2
...
flyway:
locations: classpath:/flyway/h2,classpath:/flyway/common,classpath:/flyway/testdata
test parent class:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class, FlywayTestExecutionListener.class })
#ActiveProfiles({"db_h2","logging_quiet", "http_secure_selfsigned", "credentials_insecure"})
public abstract class RestIntTestParent {
...
#Before
#FlywayTest
public void setUpAll() throws Exception {
...
}
}
an example of a REST Assured test:
public class SettingsIntTest extends RestIntTestParent {
private static final String URL = "/users/me/settings";
#Test
public void testGetAll() {
final String authTokenAlice = getAuthToken("alice");
given(this.specApi)
.header(AUTH_HEADER, authTokenAlice)
.get(URL)
.then()
.statusCode(HttpStatus.OK.value())
.body("content", hasSize(4))
.body("content[3].intVal1", equalTo(28))
.body("content[1].jsonVal[2].year", equalTo(2015));
}
}

Springboot 2.0 JUnit test #Tranactional rollback doesn't works

I migrated some projects from Springboot 1.5.10 to 2.0.
Springboot 2.0.3Release, JDK10, mysql, hikari-cp
After this work, in JUnit test, all data in test cases remains at database. I think it doesn't works #Tranactional - org.springframework.transaction.annotation.Transactional
Here is part of application.yml and test class.
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: none
database: mysql
database-platform: org.hibernate.dialect.MySQL5Dialect
Here is datasource.
#Configuration
#EnableTransactionManagement
public class DatasourceJPAConfig {
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
}
Here is part of JUnit test class.
#Transactional
#Rollback(true)
#RunWith(SpringRunner.class)
#ActiveProfiles("local")
#SpringBootTest
public class RepoTests {
#Autowired
private TestRepository testRepository;
#Test
public void saveTest() {
var name = "test";
var description = "test description"
var item = TestDomain.builder()
.name(name)
.description(description)
.build();
testRepository.save(item);
var optional = testRepository.findById(item.getId());
assertTrue(optional.isPresent());
assertEquals(optional.get().getDescription(), description);
assertEquals(optional.get().getName(), name);
}
}
after to run saveTest method, increase 1 row at database.
Add datasource to test and set auto commit to false
#Autowired
private DataSource dataSource;
And inside test
((HikariDataSource)dataSource).setAutoCommit(false);

Spring Test Dont have access on TestEntityManager

I'm trying execute some test with #DataJpaTest but I cant save my object to create my assertions.
Doc for TestEntityManager
When I try save my entity, I have the following result on log:
15/02/2018 14:58:40.565 WARN [main] org.hibernate.engine.jdbc.spi.SqlExceptionHelper: SQL Error: -5501, SQLState: 42501
15/02/2018 14:58:40.565 ERROR [main] org.hibernate.engine.jdbc.spi.SqlExceptionHelper: user lacks privilege or object not found: MY_VIEW in statement [select validviewl0_.cpf as cpf1_0_0_, validacaol0_.rating as rating7_0_0_ from dbo.my_view validviewl0_ where validviewl0_.cpf=?]
This is my annotations on test class:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace = Replace.ANY, connection = EmbeddedDatabaseConnection.HSQL)
public class MyRepositoryTest {
#Autowired
private TestEntityManager testEntityManager
#Autowired
private MyRepository myRepository;
#Before
public void setup() {
Assert.assertTrue(testEntityManager.getEntityManager().isOpen());
testEntityManager.persist(MyEntity.builder()
.cpf("11122233344").build());
testEntityManager.flush();
}
#After
public void after() {
testEntityManager.clear();
}
}
The BIG problem is that I dont know how to granw this access and it is about this message: user lacks privilege or object not found: MY_VIEW
Obs.: The real database (not in-memory and not on this test) is MS SQL Server.
It's not because of user permissions but tables are not created in your in-memory database so you need to add generate-ddl to your properties.
Also try annotating test with:
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(replace = Replace.ANY)
#Transactional
#SpringBootTest
Add H2 or HSQL database for testing (or equivalent for Maven):
testCompile 'com.h2database:h2'
Application.yml properties example:
spring:
jpa:
database: default
generate-ddl: true
properties:
hibernate:
show_sql: true
use_sql_comments: true
format_sql: true
datasource:
url: jdbc:h2:mem:your_test_db;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
driverClassName: org.h2.Driver
If you mark your test with #Transactional, database will be roll backed after test so you wouldn't need to use #After to clear it. More info at Should my tests be #Transactional?
If this does not work, try simple EntityManager instead of TestEntityManager.

Resources