java - 如何在 Mockito 单元测试期间生成 H2 嵌入式数据库?
问题描述
我目前正在开发一个 springboot API,已决定我和我的同事将在开发过程中使用 H2 嵌入式数据库。
数据库在启动应用程序时自身生成良好,但我无法在单元测试期间使其工作:它们都失败了org.h2.jdbc.JdbcSQLException: Table '[...]' not found
。
我基本上没有编写大部分代码,如果您需要更多代码,请告诉我:
application.properties
初始化 H2 数据库的文件:
datasources.member-request.url=jdbc:h2:mem:db;IGNORECASE=TRUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS DMDEOWNER\\;SET SCHEMA DMDEOWNER\\;runscript from 'classpath:h2_init_script.sql'
datasources.member-request.username=sa
datasources.member-request.password=
datasources.member-request.driver-class-name=org.h2.Driver
datasources.member-request.initialize=true
正如你在上面看到的,我们在 H2 初始化时执行了一个名为 的 SQL 脚本h2_init_script.sql
,在这个文件中我们有一些这样的 SQL 语句(例如,我将向你展示 T_THEME 表)
/* CREATE statements */
CREATE TABLE DMDEOWNER.T_THEME (
F_NUM_THEME NUMBER(14) NOT NULL,
F_REF_THEME VARCHAR2(30) NOT NULL,
F_LIB_THEME VARCHAR2(50) NOT NULL,
F_POS_THEME NUMBER(4) NOT NULL,
F_BOOL_ACTIF NUMBER(1) NOT NULL,
F_UTILISATEUR_MAJ VARCHAR2(40) NOT NULL,
F_DT_CREATION DATE NOT NULL,
F_DT_MAJ DATE,
PRIMARY KEY (F_NUM_THEME)
);
/* INSERT statements */
/* ... */
这是我的测试类(及其父类):
public class ThemeRepositoryTest extends AbstractRepositoryTest {
private final static int NB_ACTIVE_ENTITIES = 2;
private final static int NB_INACTIVE_ENTITIES = 1;
@Autowired
private ThemeRepository repository;
@Autowired
private ThemeMapper mapper;
// -------------------------------------------------------------------------
// CREATE
// -------------------------------------------------------------------------
@Before
public void init() {
for (int i = INTEGER_ZERO; i < NB_ACTIVE_ENTITIES; i++) {
insertTheme(true);
}
for (int i = INTEGER_ZERO; i < NB_INACTIVE_ENTITIES; i++) {
insertTheme(false);
}
entityManager.flush();
}
// -------------------------------------------------------------------------
// READ
// -------------------------------------------------------------------------
@Test
public void findAll() {
List<ThemeEntity> list = repository.findAll();
assertEquals(NB_ACTIVE_ENTITIES + NB_INACTIVE_ENTITIES, list.size());
}
}
@RunWith(SpringRunner.class)
@DataJpaTest
public abstract class AbstractRepositoryTest {
@Autowired
protected TestEntityManager entityManager;
protected ThemeEntity insertTheme(boolean active) {
ThemeEntity entity = newThemeEntity(3L, "NAME", active, "USER");
return entityManager.merge(entity);
}
}
这是我的错误发生的地方,在init()
我调用时的函数中insertTheme()
:
findAll(io.lacipav.repository.ThemeRepositoryTest) Time elapsed: 0.227 s <<< ERROR!
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
at io.lacipav.repository.ThemeRepositoryTest.init(ThemeRepositoryTest.java:38)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
at io.lacipav.repository.ThemeRepositoryTest.init(ThemeRepositoryTest.java:38)
Caused by: org.h2.jdbc.JdbcSQLException:
Table "T_THEME" not found; SQL statement:
select themeentit0_.f_num_theme as f_num_th1_11_0_, themeentit0_.f_bool_actif as f_bool_a2_11_0_, themeentit0_.f_dt_creation as f_dt_cre3_11_0_, themeentit0_.f_dt_maj as f_dt_maj4_11_0_, themeentit0_.f_lib_theme as f_lib_th5_11_0_, themeentit0_.f_pos_theme as f_pos_th6_11_0_, themeentit0_.f_ref_theme as f_ref_th7_11_0_, themeentit0_.f_utilisateur_maj as f_utilis8_11_0_ from t_theme themeentit0_ where themeentit0_.f_num_theme=? [42102-197]
at io.lacipav.repository.ThemeRepositoryTest.init(ThemeRepositoryTest.java:38)
由于错误告诉我它没有找到我的表,我猜这是因为在我构建.war
文件时我的数据库没有运行,如果是这样,我怎样才能更快地初始化它?
编辑:根据要求,这是 T_THEME 的实体类:
@Entity
@Getter
@Setter
@Table(name = "T_THEME")
public class ThemeEntity {
/** Primary key of the table. */
@Id
@NotNull
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "theme_generator")
@SequenceGenerator(name = "theme_generator", sequenceName = "SEQ_NUM_THEME", allocationSize = 1)
@Column(name = "f_num_theme")
private Long idTechnique;
/** Theme functional identifier */
@NotNull
@Column(name = "f_ref_theme")
private String reference;
/** Theme simple short length label */
@NotNull
@Column(name = "f_lib_theme")
private String name;
//...
}
注意:在 SQL 脚本中生成 SQL 序列“SEQ_NUM_THEME”并与 F_NUM_THEME 相关联。
编辑 2:
正如 Lesiak 指出的那样,我的错误可能来自我的 DataSource 被 annotation 替换@DataJpaTest
。通过仔细观察日志,我发现了一些有趣的行。
[INFO ] 2019-05-24 16:22:20.341 [main] org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceBeanFactoryPostProcessor.process(TestDatabaseAutoConfiguration.java:106) : Replacing 'dataSource' DataSource bean with embedded version
[INFO ] 2019-05-24 16:22:20.346 [main] org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:824) : Overriding bean definition for bean 'dataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]] with [Root bean: class [org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
[INFO ] 2019-05-24 16:22:21.050 [main] org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory.initDatabase(EmbeddedDatabaseFactory.java:189) : Starting embedded database: url='jdbc:h2:mem:4ef27020-c472-4be9-a9af-73f5e0175846;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
我们可以在最后一行看到我的 url 连接jdbc:h2:mem:db
已被替换为jdbc:h2:mem:4ef27020-c472-4be9-a9af-73f5e0175846
. 这可能是我收到一些Table not found
错误的原因。
解决方案
问题在于@DataJpaTest
你正在使用。参见文档@DataJpaTest
默认情况下,使用 @DataJpaTest 注释的测试将使用嵌入式内存数据库(替换任何显式或通常自动配置的数据源)。@AutoConfigureTestDatabase 注释可用于覆盖这些设置。
您会在日志中找到类似的内容
EmbeddedDataSourceBeanFactoryPostProcessor : Replacing 'dataSource' DataSource bean with embedded version
要修复,请使用:
spring.test.database.replace=none
spring.jpa.properties.hibernate.default_schema=DMDEOWNER
推荐阅读
- java - 如何使用 JAVA 从 Azure 的 Cosmos DB 集合中获取所有文档?
- erlang - 如何在 shell 中使用 rebar3 创建 Erlang 应用程序?
- ios - c文件可以读取Xcode中的本地化字符串吗?
- java - 如何根据系统环境属性更改枚举值
- windows - 在 Windows 机器上构建 docker 映像时出现 chmod CommandNotFoundException
- c - CC1352P 启动板 SPI 接口不适用于我的应用
- php - 如何使用按日期范围的动态 mysql 查询从数据库中获取数据
- c# - 如何诊断 .net core ANCM 进程内启动失败
- browser - 如何更改 JMeter 执行目标浏览器?
- php - 如何在日期选择器中设置动态选定月份的第一个日期?