问题
I have an issue with my integration tests of my jpa repository in a spring-boot web application. A test of a service method fails, because the accessed repository does not return any results. But the transaction for the database should contain data, because the SQL script gets executed correctly, after the log shows that the transaction for the test has begun.
If the code is used as Web-service, the data can be accessed as expected, so it seems to be a problem with the transaction of the test.
Can anyone point me to the right direction to solve this issue?
PS: @Data
is from https://projectlombok.org/, which creates a complete bean.
Here is my corresponding code:
Entity
@Entity
@Data
public class ConcreteEvent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String caption;
private String description;
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime startDate;
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime endDate;
}
Repository
public interface ConcreteEventRepository
extends PagingAndSortingRepository<ConcreteEvent, Long> {
}
Service
@Service
public class CalenderEventServiceImpl implements CalendarEventService {
@Autowired
private ConcreteEventRepository concreteEventRepository;
@Override
public List<ConcreteEvent> getCalendarEventsForDay(DateTime day) {
List<ConcreteEvent> list = new ArrayList<>();
Iterable<ConcreteEvent> findAll = concreteEventRepository.findAll();
findAll.forEach(list::add);
return list;
}
}
Test
@ActiveProfiles("test")
@SpringApplicationConfiguration(Application.class)
@WebAppConfiguration
@DirtiesContext
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
public class CalendarEventServiceTest
extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private CalendarEventService calendarEventService;
@Before
public void initialize()
{
executeSqlScript("classpath:concreteEvents.sql", false);
}
@Test
public void testGetCalendarEventsForDay_UseConcreteEvents() {
List<ConcreteEvent> calendarEventsForDateTime = calendarEventService.getCalendarEventsForDay(new DateTime(2016, 06, 20, 18, 00));
assertNotNull("No list of events retrieved", calendarEventsForDateTime);
assertEquals("Not the correct number of events retrieved", 2, calendarEventsForDateTime.size());
}
}
SQL-Script
INSERT INTO CONCRETEEVENT (ID, CAPTION, DESCRIPTION, STARTDATE, ENDDATE) values (1, 'TestEvent1', 'Test Description 1', PARSEDATETIME('2016-06-24 18:00', 'yyyy-MM-dd hh:mm'), PARSEDATETIME('2016-06-24 20:00', 'yyyy-MM-dd hh:mm'));
INSERT INTO CONCRETEEVENT (ID, CAPTION, DESCRIPTION, STARTDATE, ENDDATE) values (2, 'TestEvent2', 'Test Description 2', PARSEDATETIME('2016-06-24 18:15', 'yyyy-MM-dd hh:mm'), PARSEDATETIME('2016-06-24 20:15', 'yyyy-MM-dd hh:mm'));
Log
o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@6b09bb57 testClass = CalendarEventServiceTest, testInstance = service.CalendarEventServiceTest@556aed22, testMethod = testGetCalendarEventsForDay_UseConcreteEvents@CalendarEventServiceTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@6536e911 testClass = CalendarEventServiceTest, locations = '{}', classes = '{class api.Application}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.SpringApplicationContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.hibernate5.HibernateTransactionManager@3b66ac74]; rollback [true]
o.s.jdbc.datasource.init.ScriptUtils : Executing SQL script from class path resource [api/calendar/service/concreteEvents.sql]
o.s.jdbc.datasource.init.ScriptUtils : Executed SQL script from class path resource [api/calendar/service/concreteEvents.sql] in 7 ms.
o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context [DefaultTestContext@6b09bb57 testClass = CalendarEventServiceTest, testInstance = api.calendar.service.CalendarEventServiceTest@556aed22, testMethod = testGetCalendarEventsForDay_UseConcreteEvents@CalendarEventServiceTest, testException = java.lang.AssertionError: Not the correct number of events retrieved expected:<2> but was:<0>, mergedContextConfiguration = [WebMergedContextConfiguration@6536e911 testClass = CalendarEventServiceTest, locations = '{}', classes = '{class api.Application}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.SpringApplicationContextLoader', parent = [null]]].
o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@56620197: startup date [Fri Jun 24 22:50:25 CEST 2016]; root of context hierarchy
Configuration
HibernateTestConfiguration:
@Configuration
@Profile("test")
public class HibernateTestConfiguration extends HibernateConfiguration {
@Bean
@Override
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setPassword(environment.getRequiredProperty("jdbc.test.password"));
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
@Override
protected Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.format_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "create");
return properties;
}
}
HibernateConfiguration:
@Configuration
@EnableJpaRepositories("api")
@EnableTransactionManagement
@PropertySource(value = { "classpath:application.properties" })
@Profile("default")
public class HibernateConfiguration {
private static final String[] PACKAGES_TO_SCAN = new String[] { "api" };
@Autowired
protected Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(PACKAGES_TO_SCAN);
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(PACKAGES_TO_SCAN);
factory.setDataSource(dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public DataSource dataSource() {
// stripped for brevity
}
protected Properties hibernateProperties() {
// stripped for brevity
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
AppConfiguration:
@Configuration
@EnableAutoConfiguration
@ComponentScan("api")
@EnableWebMvc
public class AppConfiguration {
}
Application:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Dependencies
- spring-boot-starter-web: 1.3.5
- spring-boot-starter-data-jpa: 1.3.5
- spring-boot-starter-test: 1.3.5
- spring-test: 4.2.6
- spring-orm: 4.2.6
- h2: 1.4.191
回答1:
I have found my error.
In the class HibernateConfiguration
i was overwriting the transactionManager. This was taken from a tutorial and seems to be unnecessary.
So the bean transactionManager
has been removed from the class.
Also the annotations @EnableJpaRepositories("api")
, @EnableTransactionManagement
and the bean entityManagerFactory
could be removed.
回答2:
Configure H2 database
Open application.properties file, add configurations:
spring.h2.console.enabled=true
spring.h2.console.path=/h2_console
spring.datasource.url=jdbc:h2:file:~/h2/testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
来源:https://stackoverflow.com/questions/38022284/spring-jpa-repository-findall-returns-no-data-in-junit-test