Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringHibernateH2JUnit测试-如何在启动时加载模式_Java_Spring_Hibernate_Junit_H2 - Fatal编程技术网

Java SpringHibernateH2JUnit测试-如何在启动时加载模式

Java SpringHibernateH2JUnit测试-如何在启动时加载模式,java,spring,hibernate,junit,h2,Java,Spring,Hibernate,Junit,H2,我正在尝试为我的应用程序开发测试(我很晚才发现测试…),但我被卡住了,无法完成基本配置。我在谷歌上搜索了很多例子,没有一个让我满意,坦率地说,这让我有点困惑 我试图实现的是在测试开始时加载import.sql(这是来自现有MySQL模式的转储文件),并将其加载到H2数据库中 这是hibernate配置文件: @Configuration @EnableTransactionManagement @ComponentScan({ "kamienica.feature" }) public clas

我正在尝试为我的应用程序开发测试(我很晚才发现测试…),但我被卡住了,无法完成基本配置。我在谷歌上搜索了很多例子,没有一个让我满意,坦率地说,这让我有点困惑

我试图实现的是在测试开始时加载import.sql(这是来自现有MySQL模式的转储文件),并将其加载到H2数据库中

这是hibernate配置文件:

@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class HibernateTestConfiguration {

    @Autowired
    ApplicationContext applicationContext;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "kamienica" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;"
                + "INIT=CREATE SCHEMA IF NOT EXISTS kamienica;DB_CLOSE_ON_EXIT=FALSE");
        dataSource.setUsername("sa");
        dataSource.setPassword("");

        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        properties.put("hibernate.hbm2ddl.auto", "update");
// this is where I tried to load script the first time:
// properties.put("hibernate.hbm2ddl.import_files", "kamienica.sql");
        return properties;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(s);
        return txManager;
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { HibernateTestConfiguration.class })
public class BaseTest {

    private EmbeddedDatabase db;

    @Autowired
    private SessionFactory sessionFactory;

    //second attempt to load sql file
    @Before
    public void setUp() throws Exception {
        db = new EmbeddedDatabaseBuilder().addScript("import.sql").build();
    }

    @After
    public void tearDown() throws Exception {
        SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
        SessionFactoryUtils.closeSession(sessionHolder.getSession());
    }

}
每次开始测试时,我都会收到一条消息:

org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata信息: HH000262:未找到表:公寓

当我试图检索任何内容时,会得到空/空值

我尝试在hibernate配置(通过hibernate属性)以及所有测试类计划扩展的超类中加载sql文件:

@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class HibernateTestConfiguration {

    @Autowired
    ApplicationContext applicationContext;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "kamienica" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;"
                + "INIT=CREATE SCHEMA IF NOT EXISTS kamienica;DB_CLOSE_ON_EXIT=FALSE");
        dataSource.setUsername("sa");
        dataSource.setPassword("");

        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        properties.put("hibernate.hbm2ddl.auto", "update");
// this is where I tried to load script the first time:
// properties.put("hibernate.hbm2ddl.import_files", "kamienica.sql");
        return properties;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(s);
        return txManager;
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { HibernateTestConfiguration.class })
public class BaseTest {

    private EmbeddedDatabase db;

    @Autowired
    private SessionFactory sessionFactory;

    //second attempt to load sql file
    @Before
    public void setUp() throws Exception {
        db = new EmbeddedDatabaseBuilder().addScript("import.sql").build();
    }

    @After
    public void tearDown() throws Exception {
        SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
        SessionFactoryUtils.closeSession(sessionHolder.getSession());
    }

}

如何加载sql文件并准备H2数据库以执行测试?

我希望这种spring引导方法将对您有所帮助。首先在项目根目录的src/test目录中创建一个resources目录(springboot的类路径)。 在此目录中,您将开始放置名为saydata.SQL的夹具SQL数据文件。 然后,在同一级别上创建application.properties文件(同一目录请参见屏幕截图)。应按如下所示填充此文件:

spring.datasource.url = jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
#spring.datasource.url: jdbc:mysql://localhost:3306/yourDB
#spring.datasource.username = root
#spring.datasource.password =

# Hibernate
hibernate.show_sql: true
#hibernate.dialect: org.hibernate.dialect.MySQL5Dialec
spring.jpa.hibernate.ddl-auto=none
截图:

现在是测试方法

@RunWith(SpringJUnit4ClassRunner.class) 
....
            @Autowired
            private DataSource ds; //your application.properties
            @Autowired
            private WebApplicationContext context;
            private static boolean loadDataFixtures = true;
            private MockMvc mockMvc;
        ....

         @Before
         public void setupMockMvc() {
         mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }    




        @Before
            public void loadDataFixtures() {
                 if (loadDataFixtures) {
                    ResourceDatabasePopulator populator = new ResourceDatabasePopulator(context.getResource("classpath:/data.sql"));
                    DatabasePopulatorUtils.execute(populator, ds);
                    loadDataFixtures = false;
                }
            }

@Test
public void yourmethod() {
    assertEquals(3, repository.count()); //example
}

我希望这个春季启动的方法会对你有所帮助。首先在项目根目录的src/test目录中创建一个resources目录(springboot的类路径)。 在此目录中,您将开始放置名为saydata.SQL的夹具SQL数据文件。 然后,在同一级别上创建application.properties文件(同一目录请参见屏幕截图)。应按如下所示填充此文件:

spring.datasource.url = jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
#spring.datasource.url: jdbc:mysql://localhost:3306/yourDB
#spring.datasource.username = root
#spring.datasource.password =

# Hibernate
hibernate.show_sql: true
#hibernate.dialect: org.hibernate.dialect.MySQL5Dialec
spring.jpa.hibernate.ddl-auto=none
截图:

现在是测试方法

@RunWith(SpringJUnit4ClassRunner.class) 
....
            @Autowired
            private DataSource ds; //your application.properties
            @Autowired
            private WebApplicationContext context;
            private static boolean loadDataFixtures = true;
            private MockMvc mockMvc;
        ....

         @Before
         public void setupMockMvc() {
         mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }    




        @Before
            public void loadDataFixtures() {
                 if (loadDataFixtures) {
                    ResourceDatabasePopulator populator = new ResourceDatabasePopulator(context.getResource("classpath:/data.sql"));
                    DatabasePopulatorUtils.execute(populator, ds);
                    loadDataFixtures = false;
                }
            }

@Test
public void yourmethod() {
    assertEquals(3, repository.count()); //example
}

没有任何输出或完整的stacktrace,我只能建议您:

  • 您没有显示任何
    @Test
    方法。你怎么会犯这样的错误
  • 您的文件
    import.sql
    是否在
    src/test/resources
    文件夹中?(注意测试路径)
  • sql脚本的格式是否正确?您是否尝试过在导出后运行?您可以发布创建
    单元
    表的sql脚本部分吗

  • 如果所有这些都是真的,那么问题可能不在于加载sql,而在于如何使用它,或者脚本的内容,或者表的名称等等

    没有任何输出或完整的stacktrace,我只能建议您:

  • 您没有显示任何
    @Test
    方法。你怎么会犯这样的错误
  • 您的文件
    import.sql
    是否在
    src/test/resources
    文件夹中?(注意测试路径)
  • sql脚本的格式是否正确?您是否尝试过在导出后运行?您可以发布创建
    单元
    表的sql脚本部分吗

  • 如果所有这些都是真的,那么问题可能不在于加载sql,而在于如何使用它,或者脚本的内容,或者表的名称等等

    经过长时间的“调查”,我得出结论,问题隐藏在DBUnit TestNG设置的某个地方

    我决定保持它的简单性,并切换到JUnit测试

    如果其他人可能有类似的问题,以下是适用于我的配置文件:

    @Configuration
    @EnableTransactionManagement
    @ComponentScan({ "kamienica.feature" })
    public class JUnitConfig {
    
        @Bean
        public LocalSessionFactoryBean sessionFactory() {
            LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
            sessionFactory.setDataSource(dataSource());
            sessionFactory.setPackagesToScan(new String[] { "kamienica" });
            sessionFactory.setHibernateProperties(hibernateProperties());
            return sessionFactory;
        }
    
        @Bean(name = "dataSource")
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("org.h2.Driver");
            dataSource.setUrl("jdbc:h2:mem:kamienica;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
    
            dataSource.setUsername("sa");
            dataSource.setPassword("");
            return dataSource;
        }
    
        private Properties hibernateProperties() {
            Properties properties = new Properties();
            properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
            properties.put("hibernate.hbm2ddl.auto", "create");
            return properties;
        }
    
        @Bean
        public HibernateTransactionManager transactionManager(SessionFactory s) {
            HibernateTransactionManager txManager = new HibernateTransactionManager();
            txManager.setSessionFactory(s);
            return txManager;
        }
    
    }
    
    现在只需在resources文件夹中插入import.sql文件。 我还发现,每个insert语句无论有多长都必须在一行中,否则将无法加载

    最后是一个简单的测试类:

    @ContextConfiguration(classes = { JUnitConfig.class })
    @RunWith(SpringJUnit4ClassRunner.class)
    public class ApartmentServiceTest extends AbstractServiceTest{
    
        @Autowired
        ApartmentService service;
    
    
        @Test
        public void getList() {
            List<Apartment> list = service.getList();
            System.out.println(list.toString());
            assertEquals(5, list.size());
        }
    }
    
    @ContextConfiguration(类={JUnitConfig.class})
    @RunWith(SpringJUnit4ClassRunner.class)
    公共类ApartmentServiceTest扩展了AbstractServiceTest{
    @自动连线
    公寓服务;
    @试验
    public void getList(){
    List=service.getList();
    System.out.println(list.toString());
    assertEquals(5,list.size());
    }
    }
    
    经过长时间的“调查”,我得出结论,问题隐藏在数据库单元TestNG设置的某个地方

    我决定保持它的简单性,并切换到JUnit测试

    如果其他人可能有类似的问题,以下是适用于我的配置文件:

    @Configuration
    @EnableTransactionManagement
    @ComponentScan({ "kamienica.feature" })
    public class JUnitConfig {
    
        @Bean
        public LocalSessionFactoryBean sessionFactory() {
            LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
            sessionFactory.setDataSource(dataSource());
            sessionFactory.setPackagesToScan(new String[] { "kamienica" });
            sessionFactory.setHibernateProperties(hibernateProperties());
            return sessionFactory;
        }
    
        @Bean(name = "dataSource")
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("org.h2.Driver");
            dataSource.setUrl("jdbc:h2:mem:kamienica;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
    
            dataSource.setUsername("sa");
            dataSource.setPassword("");
            return dataSource;
        }
    
        private Properties hibernateProperties() {
            Properties properties = new Properties();
            properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
            properties.put("hibernate.hbm2ddl.auto", "create");
            return properties;
        }
    
        @Bean
        public HibernateTransactionManager transactionManager(SessionFactory s) {
            HibernateTransactionManager txManager = new HibernateTransactionManager();
            txManager.setSessionFactory(s);
            return txManager;
        }
    
    }
    
    现在只需在resources文件夹中插入import.sql文件。 我还发现,每个insert语句无论有多长都必须在一行中,否则将无法加载

    最后是一个简单的测试类:

    @ContextConfiguration(classes = { JUnitConfig.class })
    @RunWith(SpringJUnit4ClassRunner.class)
    public class ApartmentServiceTest extends AbstractServiceTest{
    
        @Autowired
        ApartmentService service;
    
    
        @Test
        public void getList() {
            List<Apartment> list = service.getList();
            System.out.println(list.toString());
            assertEquals(5, list.size());
        }
    }
    
    @ContextConfiguration(类={JUnitConfig.class})
    @RunWith(SpringJUnit4ClassRunner.class)
    公共类ApartmentServiceTest扩展了AbstractServiceTest{
    @自动连线
    公寓服务;
    @试验
    public void getList(){
    List=service.getList();
    System.out.println(list.toString());
    assertEquals(5,list.size());
    }
    }
    
    我不知道这对你来说是不是太过分了,但是在CI/CD的情况下,你会使用类似Flyway的东西来管理你的DB模式,为测试DB构建它是非常高兴的。我不知道这对你来说是否太过分了,但在CI/CD的情况下,你会使用类似Flyway的东西来管理你的DB模式,它非常乐意为测试数据库构建它。