Spring4 / JUnit4 嵌入式数据库未加载,可能是项目配置错误
Posted
技术标签:
【中文标题】Spring4 / JUnit4 嵌入式数据库未加载,可能是项目配置错误【英文标题】:Spring4 / JUnit4 embedded database not loading, possibly misconfigured project 【发布时间】:2016-02-09 04:47:24 【问题描述】:我以为我拥有一切,但不是真的,所以我寻求帮助。
我有一个小型 Spring 4 (WebMvc) 项目,它在 mysql 中的一个表(在我的代码中为 Location 类)上执行 CRUD 活动。我在 Tomcat 8 上的 Spring 4 中运行良好,没有单元测试。
现在我添加了单元测试,但无法正确配置 JUnit。我想我正确地设置了一个嵌入式 HSQL 数据库,但是我的 JUnit 测试说没有记录。我可以找人帮我理顺吗?
该程序实际上并没有命名为“MyProgram”,路径也不是“mypackagepath”,而是将内容编辑为缩短内容。首先,这里是工作程序的配置部分:
@Configuration
@ComponentScan(basePackages = "mypackagepath")
@EnableWebMvc
public class MyProgramConfiguration extends WebMvcConfigurerAdapter ...
@Override
public void configureViewResolvers(ViewResolverRegistry registry) ...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) ...
@Configuration
@EnableTransactionManagement
@ComponentScan( "mypackagepath.configuration" )
@PropertySource(value = "classpath:application.properties" )
@EnableJpaRepositories(basePackages = "mypackagepath.dao" )
public class JpaConfiguration
@Autowired
private Environment environment;
@Bean(name="entitymanagername")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() ...
@Bean
public DataSource dataSource() ...
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) ...
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
@Override
protected Class<?>[] getRootConfigClasses() ...
@Override
protected Class<?>[] getServletConfigClasses() ...
@Override
protected String[] getServletMappings() ...
测试代码中的类似配置有:
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "mypackagepath.configuration" ,
excludeFilters = @ComponentScan.Filter(value = JpaConfiguration.class, type = FilterType.ASSIGNABLE_TYPE ) )
public class TestJpaConfiguration
@Value("classpath:createLocationTableForTest.sql")
private String createLocationTableScript;
@Value("classpath:fillLocationTableForTest.sql")
private String fillLocationTableScript;
@Autowired
private Environment environment;
@Bean(name="myentitymanagername")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPersistenceUnitName("myentitymanagername");
em.setPackagesToScan(new String[] "mypackagepath.model" );
JpaVendorAdapter va = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(va);
em.setJpaProperties(additionalProperties());
em.afterPropertiesSet();
return em;
/*
* The individual table filling scripts are defined
* and run in the test classes.
*/
@Bean(destroyMethod = "shutdown")
public DataSource dataSource()
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.HSQL)
.addScript(createLocationTableScript)
.addScript(fillLocationTableScript)
.build();
return db;
@Bean
public PlatformTransactionManager transactionManager()
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory( this.entityManagerFactoryBean().getObject() );
return tm;
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
return new PersistenceExceptionTranslationPostProcessor();
Properties additionalProperties()
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
properties.put("jadira.usertype.autoRegisterUserTypes", environment.getRequiredProperty("jadira.usertype.autoRegisterUserTypes"));
return properties;
我在 main/resources 和 test/resources 目录中有一个 application.properties 文件。当然,“测试”具有 HSQL 属性。
我认为记录没有加载(来自 fillLocationTableForTest.sql 文件),因为我的 MySQL 版本的测试表中有很多记录(如果测试配置被忽略)并且 JUnit 测试失败:
@Test
public final void testSummaryCountTotal()
Summary summary = summaryDao.getSummary();
assertThat(summary.getCountTotal(), equalTo(12L));
这会返回 java.lang.AssertionError: Expected but was ...
对于它的价值,在我的控制台中我的 JUnit 运行给了我:
[main] INFO org.springframework.test.context.web.WebTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
[main] INFO org.springframework.test.context.web.WebTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@193948d, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1604f19, org.springframework.test.context.support.DirtiesContextTestExecutionListener@23a2f9, org.springframework.test.context.transaction.TransactionalTestExecutionListener@c0edeb, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@17e2f02]
[main] INFO org.springframework.web.context.support.GenericWebApplicationContext - Refreshing org.springframework.web.context.support.GenericWebApplicationContext@dd8682: startup date [Tue Feb 09 03:51:34 CST 2016]; root of context hierarchy
[main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'dataSource': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jpaConfiguration; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [mypackagepath/configuration/JpaConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=testJpaConfiguration; factoryMethodName=dataSource; initMethodName=null; destroyMethodName=(inferred); defined in mypackagepath.configuration.TestJpaConfiguration]
[main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'exceptionTranslation': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jpaConfiguration; factoryMethodName=exceptionTranslation; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [mypackagepath/configuration/JpaConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=testJpaConfiguration; factoryMethodName=exceptionTranslation; initMethodName=null; destroyMethodName=(inferred); defined in mypackagepath.configuration.TestJpaConfiguration]
[main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'myentitymanagername': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jpaConfiguration; factoryMethodName=entityManagerFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [mypackagepath/configuration/JpaConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=testJpaConfiguration; factoryMethodName=entityManagerFactoryBean; initMethodName=null; destroyMethodName=(inferred); defined in mypackagepath.configuration.TestJpaConfiguration]
[main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'transactionManager': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jpaConfiguration; factoryMethodName=transactionManager; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [mypackagepath/configuration/JpaConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=testJpaConfiguration; factoryMethodName=transactionManager; initMethodName=null; destroyMethodName=(inferred); defined in mypackagepath.configuration.TestJpaConfiguration]
[main] INFO org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'testJpaConfiguration' of type [class mypackagepath.configuration.TestJpaConfiguration$$EnhancerBySpringCGLIB$$d9ae76ba] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[main] INFO org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: org.hsqldb.jdbcDriver
[main] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'myentitymanagername'
INFO : org.hibernate.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [
name: myentitymanagername
...]
INFO : org.hibernate.Version - HHH000412: Hibernate Core 4.3.6.Final
INFO : org.hibernate.cfg.Environment - HHH000206: hibernate.properties not found
INFO : org.hibernate.cfg.Environment - HHH000021: Bytecode provider name : javassist
INFO : org.hibernate.annotations.common.Version - HCANN000001: Hibernate Commons Annotations 4.0.5.Final
INFO : org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
INFO : org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory - HHH000397: Using ASTQueryTranslatorFactory
INFO : org.hibernate.validator.internal.util.Version - HV000001: Hibernate Validator 5.1.3.Final
INFO : org.hibernate.type.BasicTypeRegistry - HHH000270: Type registration [java.util.Currency] overrides previous : org.hibernate.type.CurrencyType@1ffa30b
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - HHH000227: Running hbm2ddl schema export
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - HHH000230: Schema export complete
[main] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Building JPA container EntityManagerFactory for persistence unit 'myentitymanagername'
INFO : org.hibernate.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [
name: myentitymanagername
...]
INFO : org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
INFO : org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory - HHH000397: Using ASTQueryTranslatorFactory
INFO : org.hibernate.type.BasicTypeRegistry - HHH000270: Type registration [java.util.Currency] overrides previous : org.hibernate.type.CurrencyType@1ffa30b
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - HHH000227: Running hbm2ddl schema export
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - HHH000230: Schema export complete
WARN : org.hibernate.jpa.internal.EntityManagerFactoryRegistry - HHH000436: Entity manager factory name (myentitymanagername) is already registered. If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "[//location/id],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]" onto public org.springframework.http.ResponseEntity<mypackagepath.model.Location> mypackagepath.controller.LocationController.getEdit(java.lang.Long)
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "[//location/id],methods=[PUT],params=[],headers=[],consumes=[application/json],produces=[application/json],custom=[]" onto public org.springframework.http.ResponseEntity<mypackagepath.model.Location> mypackagepath.controller.LocationController.putEdit(mypackagepath.model.Location,java.lang.Long)
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "[//next/id/type/type],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]" onto public org.springframework.http.ResponseEntity<mypackagepath.model.Location> mypackagepath.controller.LocationController.getNextEdit(java.lang.Long,java.lang.String)
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "[/main],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]" onto public java.lang.String mypackagepath.controller.MainController.getMainPage()
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "[//address/address/key],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]" onto public org.springframework.http.ResponseEntity<java.lang.String> mypackagepath.controller.ProxyAccessController.getAddress(java.lang.String,java.lang.String)
[main] INFO org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/static/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
[main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@dd8682: startup date [Tue Feb 09 03:51:34 CST 2016]; root of context hierarchy
[Thread-1] INFO org.springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@dd8682: startup date [Tue Feb 09 03:51:34 CST 2016]; root of context hierarchy
[Thread-1] INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'myentitymanagername'
我的请求:有人可以帮我整理一个适用于 Tomcat 和 JUnit 的 Spring / JUnit 配置吗?
谢谢, 杰罗姆。
【问题讨论】:
【参考方案1】:我有解决问题的方法,但可能不是最好的。我仍在寻找更好的解决方案。
在我的 TestJpaConfiguration.dataSource() 中,我删除了 addScript() 调用:
@Bean(destroyMethod = "shutdown")
public DataSource dataSource()
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.HSQL)
//.addScript(createLocationTableScript)
//.addScript(fillLocationTableScript)
.build();
return db;
在每个测试 Java 文件中,我在每个 setUp() / tearDown() 对中设置了一个嵌入式数据库:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestJpaConfiguration.class , loader = AnnotationConfigWebContextLoader.class)
@WebAppConfiguration
public class SummaryDaoTest
@Value("classpath:createLocationTableForTest.sql")
private String createLocationTableScript;
@Value("classpath:fillLocationTableForTest.sql")
private String fillLocationTableScript;
@Autowired
private EmbeddedDatabase db;
@Autowired
private SummaryDao summaryDao;
@BeforeClass
public static void setUpBeforeClass() throws Exception
@AfterClass
public static void tearDownAfterClass() throws Exception
@Before
public void setUp() throws Exception
db = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript(createLocationTableScript)
.addScript(fillLocationTableScript)
.build();
@After
public void tearDown() throws Exception
db.shutdown();
// After this come the tests...
这对我有用——代码通过了它的 JUnit 测试,可以部署到 Tomcat 并且在那里工作正常。
我能否在每次测试中“不重复自己”得到改进?
谢谢, 杰罗姆。
【讨论】:
以上是关于Spring4 / JUnit4 嵌入式数据库未加载,可能是项目配置错误的主要内容,如果未能解决你的问题,请参考以下文章
Maven3.0+Spring MVC4+Spring 4+Mybatis3+junit4
CSV::MalformedCSVError: 未加引号的字段在 Ruby 中不允许 \r 或 \n
mysqlbinlog结合sed命令恢复update时未加where条件之前的数据