java - Spring Bean Injection Failing Due To Proxy -


spring version: 3.2.4.release , 3.2.9.release

mockito version: 1.8.5

i've been trying introduce h2 tests old project integration testing, , i've been running few issues. due way transactions propagating, needed mock out autowired class. i've done before, i'm running severe problems. following error message being thrown when initialising test:

org.springframework.beans.factory.beancreationexception: error creating bean name 'com.stuff.xmlitcase': injection of resource dependencies failed; nested exception org.springframework.beans.factory.beannotofrequiredtypeexception: bean named 'theprocessor' must of type [com.stuff.xmlbatchfileprocessor], of type [$proxy118] @ org.springframework.context.annotation.commonannotationbeanpostprocessor.postprocesspropertyvalues(commonannotationbeanpostprocessor.java:307)

diving bit deeper, turns out the bean in-fact proxy. if check abstractbeanfactory (round line 239), can see proxy:

sharedinstance = {$proxy117@7035} "com.stuff.xmlbatchfileprocessor@66c540d0" h = {org.springframework.aop.framework.jdkdynamicaopproxy@7039}

the problem is, i've no clue coming from. i've gone on config , dependencies, , can't find anywhere should happening.

project setup

unfortunately can't give sample project this, i'll go on test configuration. have root class extend tests:

@runwith(springjunit4classrunner.class) @contextconfiguration(locations = {"classpath:/spring/spring-test-context.xml"}) @transactionconfiguration(transactionmanager = "transactionmanager", defaultrollback = true) public abstract class abstractintegrationtest { } 

this loads in spring config , rolls transactions after each test.

the spring config nothing strange either, though there 1 difference between other module , one. transaction manager , session factory:

<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> 

in other module, i'm using entitymanagerfactory, , different transaction manager:

<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> 

the class has autowired fields, , usual @service annotation:

@service(value = "theprocessor") public final class xmlbatchfileprocessor extends batchfileprocessor implements ixmlbatchprocessor { 

finally, actual test follows:

public class xmlitcase extends abstractintegrationtest {      @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);     }  } 

if replace xmlbatchfileprocessor interface , autowire field, there aren't problems compiling. mockito, however, never replaces autowired bean mocked object. if did, wouldn't bother @resource annotations , naming service, avoiding proxy issue.

any assistance on appreciate. i'll focusing on session factory , differences there, it's quite possible i'm missing else entirely.

edit

going on sotirios' comment, had morning , indeed had missed xmlprocessor has @transactional annotation, meaning class needs proxied. if remove final declaration , let cglib enhance it, mockito replace bean when initmocks(this) called. when method called, however, cglib seems replace beans spring enhanced versions, hence overwriting mockito version.

what correct way use both mockito , spring in integration test class @transactional annotations?

alright, once realised class being proxied due @transactional annotation, solution problem became clearer. needed unwrap proxy, , set mocked object directly on that:

so in abstractintegrationtest:

/**  * checks if given object proxy, , unwraps if is.  *  * @param bean object check  * @return unwrapped object proxied, else 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; } 

then in @before:

@mock private processhelper processhelper;  @before public void setup() throws exception {     mockitoannotations.initmocks(this);      ixmlbatchprocessor ixmlbatchprocessor = (ixmlbatchprocessor) unwrapproxy(xmlprocessor);     reflectiontestutils.setfield(ixmlbatchprocessor , "processhelper", processhelper); } 

this left @autowired classes intact, while injecting correct mocked object.


Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -