spring - Duplicate bean conflicts during integration tests (multiple, merged contexts?, re: surefire vs failsafe?) -
i experiencing dependency injection errors during integration-test phase of application. think it's happening because spring firing context during unit testing, caching mock bean instances used unit tests, conflict beans fired during integration-test phase, causing di in classes fail because spring finding multiple instances of same beans (mock vs real instances).
note: issue present during integration-test phase of app. app otherwise starts, runs, , unit tests (it's webapp , run maven 3 using tomcat:run-war goal).
this basic composition of integration tests. wrote bogus 1 yesterday try , isolate issue (no di involved in test):
@runwith(springjunit4classrunner.class) @contextconfiguration(locations="file:src/main/webapp/web-inf/spring/root-context.xml") @dirtiescontext public class itnonsensetest { @test public void donothing() { system.out.println("hello, world"); assert.asserttrue(true); } } my integration tests begin prefix "it" , unit tests begin prefix "ut"
i using apache surefire unit tests, , apache failsafe integration tests:
from pom.xml:
<plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-surefire-plugin</artifactid> <version>${maven.nfire.plugin.version}</version> <configuration> <excludes> <exclude>**/it*.java</exclude> </excludes> <includes> <include>**/ut*.java</include> </includes> <skiptests> ${skipunittests} </skiptests> </configuration> <executions> <execution> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-surefire-report-plugin</artifactid> <version>${maven.nfire.plugin.version}</version> </plugin> <!-- integration tests --> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-failsafe-plugin</artifactid> <version>${maven.nfire.plugin.version}</version> <configuration> <includes> <include>**/it*.java</include> </includes> <excludes> <exclude>**/ut*.java</exclude> </excludes> <skiptests> ${skipintegrationtests} </skiptests> </configuration> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> </plugin> even when running simple itnonsensetest above, spring context fails initialize properly. since many of beans i'm trying create exist in context (as mock bean instances unit test phase), spring complaining duplicates being found.
is there way tear down context after unit test phase, , build new context integration-test phase? or doing wrong?
this root-context.xml file:
<?xml version="1.0" encoding="utf-8"?> <beans:beans xmlns:aop="http://www.springframework.org/schema/aop" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- root context: defines shared resources visible other web components --> <context:property-placeholder location="file://${conf.dir}/*.properties" /> <context:component-scan base-package="com.myapp.models, com.myapp.dao, com.myapp.service" /> <beans:import resource="simplesm-context.xml" /> <beans:import resource="datasources.xml" /> <beans:import resource="rabbit-context.xml" /> <util:properties id="swaggerprops" location="classpath:swagger.properties" /> <util:properties id="encryptionprops" location="classpath:sharedencryption.properties" /> <aop:aspectj-autoproxy /> <beans:bean name="cachemanager" class="com.google.code.ssm.spring.ssmcachemanager"> <beans:property name="caches"> <beans:set> <beans:bean class="com.google.code.ssm.spring.ssmcache"> <beans:constructor-arg name="cache" index="0" ref="defaultcache" /> <beans:constructor-arg name="expiration" index="1" value="86400" /> <beans:constructor-arg name="allowclear" index="2" value="false" /> </beans:bean> </beans:set> </beans:property> </beans:bean> <beans:bean name="defaultcache" class="com.google.code.ssm.cachefactory"> <!-- <beans:property name="cachename" value="defaultcache" /> --> <beans:property name="cacheclientfactory"> <beans:bean name="cacheclientfactory" class="com.google.code.ssm.providers.spymemcached.memcacheclientfactoryimpl" /> </beans:property> <beans:property name="addressprovider"> <beans:bean class="com.google.code.ssm.config.defaultaddressprovider"> <beans:property name="address" value="${ureg.memcached.url}:${ureg.memcached.port}" /> </beans:bean> </beans:property> <beans:property name="configuration"> <beans:bean class="com.google.code.ssm.providers.cacheconfiguration"> <beans:property name="consistenthashing" value="true" /> </beans:bean> </beans:property> </beans:bean> </beans:beans> this project's dependencies' versioning info:
<properties> <java-version>1.7</java-version> <org.springframework-version>4.0.6.release</org.springframework-version> <org.springframework.amqp.version>1.3.5.release</org.springframework.amqp.version> <org.springframework.data.version>1.6.0.release</org.springframework.data.version> <google.simple.spring.memcached.version>3.2.1</google.simple.spring.memcached.version> <maven.nfire.plugin.version>2.17</maven.nfire.plugin.version> </properties> lastly, tried adding @dirtiescontext of unit tests use springjunit4classrunner, i'm still seeing error. of unit tests structured in following manner:
@runwith(springjunit4classrunner.class) @contextconfiguration @dirtiescontext public class utadditionaldatapointsservicetest { @configuration static class additionaldatapointsserviceunittestcontextconfiguration { @bean @qualifier("props") public properties getproperties() { return mockito.mock(properties.class); } @bean @qualifier("npjdbctemplate") public namedparameterjdbctemplate getnamedparameterjdbctemplate() { return mockito.mock(namedparameterjdbctemplate.class); } @bean @qualifier("ujdbctemplate") public jdbctemplate getjdbctemplate() { return mockito.mock(jdbctemplate.class); } @bean public additionaldatapointsdao getadditionaldatapointsdao() { return mockito.mock(additionaldatapointsdaoimpl.class); } @bean public additionaldatapointservice getadditionaldatapointservice() { return mockito.mock(additionaldatapointserviceimpl.class); } } @inject additionaldatapointservice adpservice; @test public void testgetadditionaldatapoints() throws exception { list<additionaldatapoint> adplist = adpservice.getadditionaldatapoints(1); org.junit.assert.assertnotnull(adplist); } i'm confident issue mock instances cached in context during unit testing phase, because if comment out definition bean when theyre instantiated in root-context.xml file, errors duplicates go away.
the stack traces same, along lines of:
nested exception org.springframework.beans.factory.nouniquebeandefinitionexception: no qualifying bean of type [java.util.properties] defined: expected single matching bean found 2: realinstancebeanname,mockinstancebeannamegetter
Comments
Post a Comment