Spring JPA Repository findAll 在 JUnit 测试中不返回任何数据
Posted
技术标签:
【中文标题】Spring JPA Repository findAll 在 JUnit 测试中不返回任何数据【英文标题】:Spring JPA Repository findAll returns no data in JUnit test 【发布时间】:2016-06-24 21:20:13 【问题描述】:我的 jpa 存储库在 spring-boot Web 应用程序中的集成测试存在问题。 服务方法的测试失败,因为访问的存储库没有返回任何结果。但是数据库的事务应该包含数据,因为在日志显示测试事务已经开始之后,SQL 脚本会正确执行。
如果将代码用作Web-service,数据可以按预期访问,所以似乎是测试的事务有问题。
谁能指出我解决这个问题的正确方向?
PS:@Data
来自 https://projectlombok.org/,它创建了一个完整的 bean。
这是我对应的代码:
实体
@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;
存储库
public interface ConcreteEventRepository
extends PagingAndSortingRepository<ConcreteEvent, Long>
服务
@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;
测试
@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 脚本
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'));
日志
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
@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;
休眠配置:
@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;
应用配置:
@Configuration
@EnableAutoConfiguration
@ComponentScan("api")
@EnableWebMvc
public class AppConfiguration
应用:
@SpringBootApplication
public class Application
public static void main(String[] args)
SpringApplication.run(Application.class, args);
依赖关系
spring-boot-starter-web: 1.3.5 spring-boot-starter-data-jpa: 1.3.5 spring-boot-starter-test: 1.3.5 弹簧测试:4.2.6 spring-orm:4.2.6 h2: 1.4.191【问题讨论】:
【参考方案1】:我发现了我的错误。
在HibernateConfiguration
类中,我覆盖了事务管理器。这是从教程中摘录的,似乎没有必要。
因此 bean transactionManager
已从类中删除。
还可以删除注释@EnableJpaRepositories("api")
、@EnableTransactionManagement
和bean entityManagerFactory
。
【讨论】:
如果这确实是您问题的答案,您可以将您的答案标记为已接受的答案。【参考方案2】:配置 H2 数据库 打开application.properties文件,添加配置:
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
【讨论】:
以上是关于Spring JPA Repository findAll 在 JUnit 测试中不返回任何数据的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA 提供的各种Repository接口作用
spring boot: spring-data-jpa (Repository/CrudRepository) 数据库操作, @Entity实体类持久化
使用 RepositoryItemReader 和 Repository Item writer 的 spring 数据 JPA 的 spring 批处理