Spring Test Dont have access on TestEntityManager - spring

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.

Related

Spring boot application not using the DB driver defined in application-test.properties

I decided I would like to add a h2 DB to my spring boot application for testing purposes. I added a new application-test.properties to my folder test/resources with all the necessary configuration. The problem is that when I run the tests, I always get the connection to the mysql database.
I can see the application-test.properties is being used because the loggin.level changes from DEBUG to ERROR in my tests.
For my MySql DB I have a file which provides the datasource
Code
application-test.properties file
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username = sa
spring.datasource.password =
spring.datasource.driver-class-name = org.h2.Driver
spring.h2.console.enabled=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.springframework.security=ERROR
application.properties file
mysql.database.host=localhost
mysql.database.port=3306
mysql.database.db=mydb
mysql.database.user=root
mysql.database.password=root
mysql.database.driver=mysql
logging.level.org.springframework.security=DEBUG
datasource class
#Bean
open fun getDataSource(): DataSource? {
val dataSourceBuilder = DataSourceBuilder.create()
dataSourceBuilder.url("jdbc:$driver://$databaseHost:$databasePort/$databaseName")
dataSourceBuilder.username(databaseUser)
dataSourceBuilder.password(databasePassword)
return dataSourceBuilder.build()
}
test
#SpringBootTest
#AutoConfigureMockMvc
#ActiveProfiles("test")
class AdAccountControllerTest {
#Autowired
lateinit var mockMvc: MockMvc
#Test
fun `we should get unauthorized status when we dont provide credentials`() {
mockMvc.perform(get("/api/v1/ad-account"))
.andExpect(status().isOk)
.andDo(print())
}
}

What kind of test shall I use in my spring project(and am I doing it right)?

My project is a simple management system for shop which is connected to MySQL database.
I only have JUnit test like this one(is this test written correctly?):
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class EmployeeRepositoryIntegrationTest
{
#Autowired
private TestEntityManager entityManager;
#Autowired
private EmployeeRepository employeeRepository;
#Test
public void whenFindByLastName_thenReturnEmployee()
{
User employee = new User("UserName","password","John",
"Smith","Adress Test","123123123","CityTest");
entityManager.persist(employee);
entityManager.flush();
User result = userRepository.findUserByLastName(employee.getLastName()).get(0);
assertThat(result.getLastName()).isEqualTo(employee.getLastName());
}
}
Should I add Mockito Tests, and what kind of test should I add in future?
I would avoid Mockito to test you JPA repoistories.
Better to seed an in-memory database (which can be spun up and torn down) with real test data.
If you're using the #DataJpaTest annotation you're expected to use sql to seed your database, look at this #DataJpaTest example. You can use sql files and get rid of the TestEntityManager.
Take a look at this DBUnit example. You add your test data in an XML file in your resources directory.

Spring Boot #ApplicationProperties not using values from test profile

I have created a class annotated with #ApplicationProperties
#Configuration
#ConfigurationProperties(prefix = "myapp.security")
class SecurityProperties {
lateinit var signingKey: String
}
And a test to see if the values are retrieved from the config file
#ExtendWith(SpringExtension::class)
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#SpringBootTest
#Profile("security-properties-test")
class SecurityPropertiesTest {
#Autowired
lateinit var securityProperties: SecurityProperties
#Test
fun `security properties are set`(){
securityProperties.signingKey shouldBe "theSigningKey"
}
}
When I create some values in the default application.yml, the value is picked up and everything works
spring:
jpa:
show-sql: true
myapp:
security:
signing-key: theSigningKey
But when I try to override the value in a profile, the value from the default profile is still used
spring:
jpa:
show-sql: true
myapp:
security:
signing-key: theSigningKey
---
spring:
profiles: security-properties-test
myapp:
security:
signing-key: anothertheSigningKey
What am I missing here?
You have used the wrong annotation on your test class. It should be annotated with #ActiveProfiles rather than #Profile.

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

Loading initial test data in H2 in 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
}
}

Resources