Why NoSuchBeanDefinedException while running Spring Integration test

112 Views Asked by At

I have a Spring Boot project for which one of the developers has written Integration tests against an in-memory DB. Here is some background before I put my question :
We have following Maven modules :
1) web-persistence : which store all entities and interfaces and corresponding implementations. All these classes are in package com.mycompany.persistence.
2) web-services : which stores all our rest controllers and spring security related classes. These are all in package com.mycompany.services
3) web-services module has maven module dependency on web-persistence module.
4) In web-services module we have defined a service UserContextServiceImpl which is implementation of interface IUserContextService. This service basically encapsulates Spring's SecurityContextHolder functionality by exposing only those parts of a current user related information which is needed through its methods so that everywhere we don't have to use SecurityContextHolder. The implementation class is annotated with @Service("userContextService").
5) Interface IUserContextService is in persistence module. There is another class AppDependecyHeper in persistence module which implements ApplicationContextAware and returns UserContextService's concrete instance by calling appContext.getBean('userContextService') where appContext is holding ApplicationContext when application is initialized.
6) Now we don't want to expose Spring Security classes in persistence module(for reasons which are out of context here) and hence above arrangement of getting current user information through a service by calling getBean() method of applicationContext in persistence layer class AppDependencyHelper. This information is then used to update audit fields createdBy and modifiedBy using an EntityListener.
7) Actual application uses only single ApplicationContext where both persistence layer classes and web controllers are loaded in one single spring context.
8) Everything works fine when application runs. However when our integration test Runs the call appContext.getBean('userContextService') fails and throws NosuchBeanDefinitionException as it is unable to find the bean with name 'userContextService'
9) Now finally the code of our integration Test (only giving relevant details) which is located in com.mycompany.persistence.embeddeddb package:

  @Runwith(SpringJUnit4ClassRunner.class)
  @ConfigurationContext 
  class MyEntityTest{

        @Configuration
        @ComponentScan("com.mycompany.persistence")  
        public static class Config{
              .....
        }
        .....//code which eventually gives call to  
        AppDependencyHelper's method which in turn tries to retrieve userContextService Bean.
  }

Now the questions :
1) Why it fails to retrieve the bean? I have tried addingcom.mycompany.services like below

@ComponentScan({"com.mycompany.persistence","com.mycompany.services"})
but to no avail.
2) What I am able to understand by reading whatever I got is that @ContextConfiguration needs to be provided with either XML files or Annotated classes or WebApplicationInitializers(in my case as we are having only single ApplicationContext) to create an ApplicationContext from @Configuration classes. However I cannot do that as maven starts complaining about circular dependency which is rightly so as my @Service annotated class UserContextServiceImpl is in web-services module which is dependent on web-persistence module already where the test case class is written.
3) The only solution I can think of is moving all integrations test classes to web-services module so that I can tell @ConfigurationContext all the classes from which it should create an ApplicationContext.Am I right?

Last point : The ApplicationContext class is of type GenericApplciationContext when I run tests. When I run application its obviously AnnotatedEmbeddedWebApplicationContext

please let me know if there is any solution to this problem?

1

There are 1 best solutions below

6
Stefan Haberl On

From what I'm guessing you are trying to use a component from your web-service module in your integration tests. If that's the case, than yes, you should move your integration test cases to your web-service module - as you've already suggested in your question.

EDIT: You should really rethink your design, because you have a circular dependency problem here: Your web-service module depends on web-persistence, but the implementation of your IUserContextService in web-persistence is found in web-service.

You should probably move your IUserContextService (and all your integration tests) to your web-service package.