Spring JPA Repository findAll在JUnit测试中不返回任何数据

时间:2016-06-24 21:20:13

标签: spring hibernate jpa junit repository

我在spring-boot Web应用程序中对jpa存储库的集成测试存在问题。 对服务方法的测试失败,因为访问的存储库不会返回任何结果。但是数据库的事务应该包含数据,因为在日志显示测试的事务已经开始之后,SQL脚本会正确执行。

如果代码用作Web服务,则可以按预期访问数据,因此测试事务似乎存在问题。

有人能指出我正确的方向来解决这个问题吗?

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

配置

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 {

}

应用:

@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
  • spring-test:4.2.6
  • spring-orm:4.2.6
  • h2:1.4.191

2 个答案:

答案 0 :(得分:2)

我发现了我的错误。

在班级HibernateConfiguration中,我覆盖了transactionManager。这是从教程中获取的,似乎没必要。

因此已从类中删除了bean transactionManager

此外,还可以删除注释@EnableJpaRepositories("api")@EnableTransactionManagement和bean entityManagerFactory

答案 1 :(得分:0)

配置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