0

I have a Spring application (3.2.4.RELEASE) which I'm trying to set up some JUnit(4.12) tests. The scenario I'm having is as follows:
I have a parent class which contains two properties with their getters and setters, and several child classes inheriting from this class. The idea is that I want to optionally be able to set these values in the pom.xml, and if not, resort to the default value returned by the base class. The code looks like the following:

Parent class:

    @Setter
public class NetworkFactoryMockTest
{
   private String imei;
   private String imsi;

   public String getImei()
   {
      return StringUtils.defaultIfEmpty(imei, "11111");
   }

   public String getImsi()
   {
      return StringUtils.defaultIfEmpty(imsi, "22222");
   }

}

Child class:

public class CrmManagerTest extends NetworkFactoryMockTest implements CrmManager
{
...
}

pom.xml:

<bean id="crmManager"
        class="com.foo.CrmManagerTest">
        <property name="imsi" value="33333" />
    </bean>

JUnit class:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/service-context-debug.xml")
@Getter @Setter
public class DiscoveryServiceAbstractTest
{   
   @Autowired
   protected ApplicationContext testApplicationContext;

   @Test
   public void testContextShouldBeProvided()
   {
      assertNotNull("Application context must be provided", testApplicationContext);
   }

}

I am using lombok to auto-generate the getters and setters, so that is definitely not the issue here. The thing is that when I run the application as Java application (SpringBoot), it works perfectly, setting all the values as they should.
However when I run the JUnit class, I'm getting the following error:

1 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@7caff0c4] to prepare test instance [com.foo.network.DiscoveryServiceAbstractTest@2e813d0] java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99) at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122) at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:105) at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:74) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'networkFactory': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.foo.network.crm.CrmManager com.foo.network.NetworkFactoryTest.crmManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crmManager' defined in class path resource [service-context-debug.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'imsi' of bean class [com.foo.network.crm.CrmManagerTest]: Bean property 'imsi' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:120) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248) at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64) at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91) ... 25 more Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.foo.network.crm.CrmManager com.foo.network.NetworkFactoryTest.crmManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crmManager' defined in class path resource [service-context-debug.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'imsi' of bean class [com.foo.network.crm.CrmManagerTest]: Bean property 'imsi' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) ... 41 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crmManager' defined in class path resource [service-context-debug.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'imsi' of bean class [com.foo.network.crm.CrmManagerTest]: Bean property 'imsi' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1423) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1128) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) ... 43 more Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'imsi' of bean class [com.foo.network.crm.CrmManagerTest]: Bean property 'imsi' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter? at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1042) at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:902) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1420) ... 54 more

A small peak into Spring internal led me to conclude that when the application is run as Java app, the setters and getters are being added as methods for the child bean, and they are used to inject the value later. However when run as JUnit test, this does not seem to happen.
Anyone has an idea what the error might be?

EDIT: After more testing I found out that the problem is not in the parent class. Even if I add the properties (imei and imsi) directly in the child class (CrmManagerTest) with explicit getters and setters and remove the extends notation, I still have the same error. Seems like spring is unable/unwilling to autowire the properties for this class. Anyone could help me figure this out?

Waddah Ajaj
  • 121
  • 1
  • 10

2 Answers2

0

The error suggest, the test is unable to load the application context file

Please refer this question

Failed to load ApplicationContext for JUnit test of Spring controller

Hopefully it will help you.

Community
  • 1
  • 1
rpfun12
  • 89
  • 6
  • Unfortunately, the error is only related to the fields in the parent class. If I remove the "imsi" property from the declaration of the bean in spring context, the test works fine. – Waddah Ajaj Mar 10 '17 at 16:12
  • Now I read the entire error message, I see the issue :) The imsi property doesn't have or incorrect setter method – rpfun12 Mar 10 '17 at 16:17
  • the setter for imsi is in the parent class. Like I said I'm using [lombok](https://projectlombok.org/) to initiate the getters and setters. This configuration is working fine. – Waddah Ajaj Mar 10 '17 at 16:24
  • Can you please try javap to disassembles NetworkFactoryMockTest.class to make sure whether you have setters ? – rpfun12 Mar 10 '17 at 16:49
0

Spring Bean definition inheritance has nothing to do with Java class inheritance but the inheritance concept is same.

You'll need to have a bean definition for the parent class, then you can do this-

<bean id="crmManager" class="com.foo.CrmManagerTest" parent="networkFactoryMockTest"> <property name="imsi" value="33333" /> </bean>
pkoli
  • 646
  • 8
  • 21
  • That did not work :( weirdly it is working when I run the application as Java, and doesn't run even when I manually add the property in the child class as JUnit. I'm inclined to think JUnit with Spring does not set the fields values – Waddah Ajaj Mar 10 '17 at 16:22
  • Have you tried adding setters to NetworkFactoryMockTest, there seem to be no setters. – pkoli Mar 10 '17 at 16:26
  • Yes, as I said I'm using [lombok](https://projectlombok.org/features/GetterSetter.html). That's the purpose of the **@Setter** annotation – Waddah Ajaj Mar 10 '17 at 16:28
  • Googling for the solution has brought me here - https://issuetracker.springsource.com/plugins/servlet/mobile#issue/STS-4133 – pkoli Mar 10 '17 at 16:45