简体   繁体   English

Spring JPA存储库findAll在JUnit测试中不返回任何数据

[英]Spring JPA Repository findAll returns no data in JUnit test

I have an issue with my integration tests of my jpa repository in a spring-boot web application. 我在spring-boot Web应用程序中对jpa存储库的集成测试有问题。 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. 但是,数据库的事务应包含数据,因为在日志显示测试事务已开始后,SQL脚本已正确执行。

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. 如果将代码用作Web服务,则可以按预期访问数据,因此这似乎与测试事务有关。

Can anyone point me to the right direction to solve this issue? 谁能指出我正确的方向来解决这个问题?

PS: @Data is from https://projectlombok.org/ , which creates a complete bean. PS: @Data来自https://projectlombok.org/ ,它创建了一个完整的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 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'));

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: 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: 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: 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-web:1.3.5
  • spring-boot-starter-data-jpa: 1.3.5 spring-boot-starter-data-jpa:1.3.5
  • spring-boot-starter-test: 1.3.5 spring-boot-starter-test:1.3.5
  • spring-test: 4.2.6 春季测试:4.2.6
  • spring-orm: 4.2.6 春季orm:4.2.6
  • h2: 1.4.191 h2:1.4.191

I have found my error. 我发现了我的错误。

In the class HibernateConfiguration i was overwriting the transactionManager. 在类HibernateConfiguration我覆盖了transactionManager。 This was taken from a tutorial and seems to be unnecessary. 这是从教程中提取的,似乎是不必要的。

So the bean transactionManager has been removed from the class. 因此,bean transactionManager已从类中删除。

Also the annotations @EnableJpaRepositories("api") , @EnableTransactionManagement and the bean entityManagerFactory could be removed. 另外,注释@EnableJpaRepositories("api") @EnableTransactionManagement和bean entityManagerFactory可以被删除。

Configure H2 database 配置H2数据库
Open application.properties file, add configurations: 打开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  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM