0

I have used @Profile in my class like this.

@Service("myClass")
@Profile(value = {"stage", "uat", "prod"})
  public class MyClass{        
    //some code
  }         

I am autowiring MyClass in another class say YourClass.

public class YourClass{
  // some code 

  @Autowired
  private MyClass myClass;
  //some code
}

Now when I run junit, it is giving unsatisfied dependency error as MyClass profile is set only for uat, stage and prod but not for unit. Is there any way by which I can autowire this myClass but it should be ignored when I am running junit?

Error stack trace

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yourClass': Unsatisfied dependency expressed through field 'myClass'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'MyClass' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1348)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$23/1013364696.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
    ... 51 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'MyClass' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
    ... 65 more

How do I solve this autowiring problem?

Vasilisa
  • 4,604
  • 3
  • 20
  • 25
  • If you do not need to run the test via spring, just use [constructor injection instead of field injection](https://stackoverflow.com/questions/40620000/spring-autowire-on-properties-vs-constructor), then simply instantiate `YourClass` by passing your own instance (maybe a mock) of `MyClass`, thus the "_spring automagic_" will no longer occur. – Morfic Mar 08 '19 at 14:51

1 Answers1

0

You cannot ignore @Autowired MyClass when running tests. When test case is run and class "YourClass" is instantiated, Spring will try to inject a bean "MyClass" in it and you are not providing it.

What you can do is to create a Mock or Stub object within test case in order to substitute "MyClass" object.

I suggest you look at this: https://www.tutorialspoint.com/mockito/mockito_junit_integration.htm

Test cases should have structure similar to this:

@InjectMocks
YourClass yourClass;

@Before
public void init(){
     MockitoAnnotations.initMocks(this);
}

@Test
public void testcase(){
      YourClass yourClass = Mockito.mock(YourClass.class);

      when(yourClass.someMethod()).thenReturn("someResponse);

      /** do stuff **/
}

Good luck!

  • Hey thanks man , but my problem is not just with this junit . Any junit that I run for any other class fails due this autowiring problem, while loading the application context it fails – Rachana Ramesh Mar 09 '19 at 14:30
  • No problem! Can you create a dummy class with "test" profile so that the Spring injects that instead of the one you have currently written. You need to supply some instance of YourClass to Spring in order for it to run correctly - as seen in the error logs. – Amer Šurković Mar 10 '19 at 23:12