【问题标题】:Adding mock breaks database tests添加模拟中断数据库测试
【发布时间】:2018-06-06 18:50:28
【问题描述】:

我用谷歌搜索了我能想到的所有东西,但都无济于事。我正在使用 Spring 4.3.1 运行。

我继承了一个应用程序,并正在尝试加强单元测试以使其有用。

作为其中的一部分,我在单元测试中添加了以下行:

Mockito.when(udfConfigurationRepository.save(any(UDFConfiguration.class))).thenAnswer(parm -> parm.getArguments()[0]);

单元测试运行良好。然后我为该应用程序运行构建并收到以下错误:

java.lang.IllegalStateException: Failed to load ApplicationContext

    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213)
    at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138)
    at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:175)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:107)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [applicationContext-dao-test.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: error trying to scan <jar-file>: file:/C:/casenet/Sources/provider-portal/portal-server/target/test-classes
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 28 more
Caused by: java.lang.RuntimeException: error trying to scan <jar-file>: file:/C:/casenet/Sources/provider-portal/portal-server/target/test-classes
    at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:855)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:597)
    at org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateEjbPersistenceProvider.java:50)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
    ... 43 more
Caused by: java.lang.RuntimeException: Error while reading file:/C:/casenet/Sources/provider-portal/portal-server/target/test-classes
    at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:131)
    at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:485)
    at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:852)
    ... 50 more
Caused by: java.io.IOException: invalid constant type: 18
    at javassist.bytecode.ConstPool.readOne(ConstPool.java:1113)
    at javassist.bytecode.ConstPool.read(ConstPool.java:1056)
    at javassist.bytecode.ConstPool.<init>(ConstPool.java:150)
    at javassist.bytecode.ClassFile.read(ClassFile.java:765)
    at javassist.bytecode.ClassFile.<init>(ClassFile.java:109)
    at org.hibernate.ejb.packaging.AbstractJarVisitor.checkAnnotationMatching(AbstractJarVisitor.java:246)
    at org.hibernate.ejb.packaging.AbstractJarVisitor.executeJavaElementFilter(AbstractJarVisitor.java:212)
    at org.hibernate.ejb.packaging.AbstractJarVisitor.addElement(AbstractJarVisitor.java:173)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:126)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:134)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:134)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:134)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:134)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.getClassNamesInTree(ExplodedJarVisitor.java:134)
    at org.hibernate.ejb.packaging.ExplodedJarVisitor.doProcessElements(ExplodedJarVisitor.java:92)
    at org.hibernate.ejb.packaging.AbstractJarVisitor.getMatchingEntries(AbstractJarVisitor.java:149)
    at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:128)
    ... 52 more

在通过 Spring 实际测试存储库的所有测试中再次发生此错误。我唯一能想到的是,通过嘲笑这个 repo,它把 Spring 的工作搞砸了。

所有的数据库测试都继承自这个基类。

@ContextConfiguration(locations = { "/applicationContext-dao-test.xml" })
@Transactional
@TestExecutionListeners( { TransactionalTestExecutionListener.class })
public class BaseRepositoryTest extends AbstractTestNGSpringContextTests{
    public BaseRepositoryTest(){ super(); }
}

这里是applicationContext-dao-test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
       xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context = "http://www.springframework.org/schema/context"
       xmlns:jpa = "http://www.springframework.org/schema/data/jpa" xmlns:p = "http://www.springframework.org/schema/p"
       xmlns:tx = "http://www.springframework.org/schema/tx"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan  base-package="com.casenet.portals.repository" />
    <context:component-scan  base-package="com.casenet.portals.services" />

    <jpa:repositories base-package = "com.casenet.portals.repository"/>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
        <property name="dataSource" ref="portalDataSource"/>
        <property name="packagesToScan">
            <list>
                <value>com.casenet.portals.repository</value>
                <value>com.casenet.portals.domain</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
            </props>
        </property>
    </bean>

    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence-test.xml" />
        <property name="persistenceUnitName" value="casenet" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
            </bean>
        </property>
    </bean>

    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="portalDataSource"/>
        <property name="jpaDialect" ref="jpaDialect" />
    </bean>


    <bean id="portalDataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource"
          p:driverClassName="org.hsqldb.jdbcDriver"
          p:url="jdbc:hsqldb:mem:casenetApplication;sql.enforce_strict_size=true"
          p:username="sa"
          p:password="" />

    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

现在所有这些测试再次失败,唯一的变化是模拟我的存储库的一行。

我有一种感觉,这与上下文有关,我可以通过这种方式修复它,但似乎找不到将它们分开的正确方法。

【问题讨论】:

  • 我可以从堆栈跟踪中看到一定有一些不同的地方,你看过stackoverflow.com/questions/30313255/… 了吗?
  • @mrkernelpanic 哇!出色的通话!你想写一个答案,以便我给你信用吗?

标签: java spring hibernate testng hsqldb


【解决方案1】:

如 cmets 所示,答案在于 Reflections - Java 8 - invalid constant type

事实证明,constant: 18 是指将 java 8 风格的 lambdas 与未在 java 8 下编译的库一起使用时出现的问题。

所以为了解决这个问题,我不得不编写更多代码如下:

Mockito.when(udfConfigurationRepository.save(any(UDFConfiguration.class))).thenAnswer(new Answer<UDFConfiguration>() {
        @Override
        public UDFConfiguration answer(InvocationOnMock invocationOnMock) throws Throwable {
            UDFConfiguration config = (UDFConfiguration) invocationOnMock.getArguments()[0];
            return config;
        }
    });

这样做修复了这个单元测试和所有其他测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-23
    • 2019-06-04
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多