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?