当前位置: 首页 > 面试题库 >

Spring bea注射失败,由于代理

曾涵育
2023-03-14
问题内容

spring版 :3.2.4.RELEASE和3.2.9.RELEASE

Mockito版本 :1.8.5

我一直在尝试将H2测试引入一个用于集成测试的旧项目,并且遇到了一些问题。由于事务传播的方式,我需要模拟一个自动装配的类。我以前已经做过,但是现在遇到了严重的问题。初始化测试时将引发以下错误消息:

org.springframework.beans.factory.BeanCreationException:创建名称为’com.stuff.XMLITCase’的bean时出错:注入资源依赖项失败;嵌套的异常是org.springframework.beans.factory.BeanNotOfRequiredTypeException:
名为“ TheProcessor”的Bean必须为[com.stuff.XMLBatchFileProcessor]类型,但实际上
在org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
类型为[$ Proxy118]
postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:307)

深入探讨一下,事实证明该bean实际上是代理。如果检查AbstractBeanFactory(第239行),则可以看到代理:

sharedInstance = {$ Proxy117 @ 7035}“
com.stuff.XMLBatchFileProcessor@66c540d0” h =

唯一的问题是,我不知道这是从哪里来的。我已经遍历了配置和依赖项,并且找不到任何应该发生的地方。

项目设置

不幸的是,我无法为此提供示例项目,但是我将介绍我的测试配置。我有一个扩展用于测试的根类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/spring-test-context.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public abstract class AbstractIntegrationTest {
}

这只是加载了一些spring配置,并在每次测试后回滚事务。

尽管我的其他模块与该模块之间有一个区别,但spring config也并不奇怪。这是事务管理器和会话工厂:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>

<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
...
</bean>

在我的其他模块中,我使用的是entityManagerFactory和其他事务管理器:

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

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>

实际上,类具有一些自动装配的字段,以及通常的@Service批注:

@Service(value = "TheProcessor")
public final class XMLBatchFileProcessor extends BatchFileProcessor implements IXMLBatchProcessor {

最后,实际测试如下:

public class XMLITCase extends AbstractIntegrathtml" target="_blank">ionTest {

    @Resource(name = "TheProcessor")
    @InjectMocks
    private XMLBatchFileProcessor xmlProcessor;

    @Mock
    private ProcessHelper processHelper;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() throws Exception {
        Assert.assertNotNull(xmlProcessor);
    }

}

如果我将XMLBatchFileProcessor替换为该接口并自动将该字段连接起来,那么编译就不会有任何问题。但是,Mockito永远不会用模拟对象替换自动装配的Bean。如果确实如此,那么我将不必理会@Resource批注和命名服务,从而避免了代理问题。

任何帮助,将不胜感激。我将重点讨论会话工厂及其之间的差异,但是我很可能会完全遗漏其他东西。

编辑

继续Sotirios的评论,今天早上我又看了一眼,确实错过了xmlProcessor有@Transactional注释,因此这意味着需要代理该类。如果我删除该final声明并让CGLib对其进行增强,那么Mockito会在initMocks(this)调用时替换该bean
。但是,当调用方法时,CGLib似乎用Spring增强版本替换了所有bean,因此覆盖了Mockito版本。

在带有@Transactional注释的类的集成测试中,同时使用Mockito和Spring的正确方法是什么?


问题答案:

好吧,一旦我意识到由于有@Transactional注释而要对课程进行代理,问题的解决方案就变得更加清晰了。我需要做的是拆开代理,然后直接在其上设置模拟对象:

所以在我的AbstractIntegrationTest

/**
 * Checks if the given object is a proxy, and unwraps it if it is.
 *
 * @param bean The object to check
 * @return The unwrapped object that was proxied, else the object
 * @throws Exception
 */
public final Object unwrapProxy(Object bean) throws Exception {
    if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
        Advised advised = (Advised) bean;
        bean = advised.getTargetSource().getTarget();
    }
    return bean;
}

然后在我的@Before

@Mock
private ProcessHelper processHelper;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);

    IXMLBatchProcessor iXMLBatchProcessor = (IXMLBatchProcessor) unwrapProxy(xmlProcessor);
    ReflectionTestUtils.setField(iXMLBatchProcessor , "processHelper", processHelper);
}

@Autowired在注入正确的模拟对象的同时,所有类都保持完整。



 类似资料:
  • 问题内容: 春季版 :3.2.4.RELEASE和3.2.9.RELEASE Mockito版本 :1.8.5 我一直在尝试将H2测试引入一个用于集成测试的旧项目,并且遇到了一些问题。由于事务传播的方式,我需要模拟一个自动装配的类。我以前做过,但是现在遇到了严重的问题。初始化测试时将引发以下错误消息: org.springframework.beans.factory.BeanCreationEx

  • Spring版本:3.2.4.版本和3.2.9.版本 Mockito版本:1.8.5 我一直在尝试将H2测试引入到一个老项目的集成测试中,并且遇到了一些问题。由于事务传播的方式,我需要模拟一个自动连接的类。我以前这样做过,但是现在遇到了严重的问题。初始化测试时会引发以下错误信息: org.springframework.beans.factory.BeanCreationException:创建名

  • 我正在尝试发布mvn,但由于git的问题,它失败了。我以前多次这样做都没有遇到这个问题,我真的不明白为什么会发生这种情况。 我首先是在mvn release:prepare中得到它的,但通过在我的根pom中添加下面显示的最后一行来绕过它: 但是现在,当我尝试做mvn发布:执行时,我再次收到错误消息: 我不明白它从哪里得到的想法,我的git安装文件夹应该是一个git存储库!错误发生前记录的git c

  • 我试图在模拟器上用Appium启动一个iOS应用程序。 Appium:1.17.1版本 处理命令时发生未知的服务器端错误。原始错误:由于xcodebuild失败,无法启动WebDriverAgent:xcodebuild失败,代码为70 xcodebuild错误消息: (Selenium::WebDriver::error::unknownerror)unknownerror:处理命令时发生未知的

  • 我是ios appium的新手,试图使用appium进行应用程序测试,我没有源代码也没有ios开发者帐户,该应用程序是从Crashlytics下载的。 Selenium.common.exceptions.WebDriverException在处理命令时发生未知的服务器端错误。原始错误:由于xcodebuild失败,无法启动WebDriverAgent:“xcodebuild失败,代码为65”。

  • 我使用Gradle 4.10.2(但使用最新版本让它工作会很好)。这是我的gradle文件: 当我执行时,它会失败并出现很多错误。这些错误都是由于没有找到lombok自动生成的getter、setter等。如何解决这些错误?我看过其他关于这个问题的帖子,他们都建议将lombok依赖项添加为 使现代化 以下是我得到的几个错误: 日志应该来自注释。并且来自于在CarDto上注释的@Builder(Bu