Use Spring application properties without starting server [duplicate] - spring-boot

This question already has an answer here:
Spring-boot application-test.properties
(1 answer)
Closed 2 years ago.
We are using Spring Boot 2.3.4
We have some Unit tests where we would only need the application.properties to be loaded (with all it's profile management aso.).
Is it possible to do that without starting the complete Spring Boot server?
EDIT:
I tried the #SpringBootTest annotation, but it always started the whole server, because I referenced the #SpringBootApplication class (or it was referenced automatically).
Actually you don't need all the other annotation, like #ConfigurationProperties
All you need is #SpringBootApplication(classes = AClass.class), where AClass is any class that doesn't have a main method, like your test class for example.

Annotate your test class with #SpringBootTest to load the context.

Related

#SpringBootTest loads unrequired Bean when making IT

I'm making some Integration Tests for my app and I'm encountering this problem I can't see how to solve.
I'm using Spring Boot 2.4.13 + Spring Data Neo4J 6.1.9
FYI, I deleted the Application default test that comes bundled when you create a project through Spring Initializr, and under /src/test/resources I have a .yml file named application.yml
My IT class looks like this:
#SpringBootTest
public class ClientIT {
#Autowired
private ClientServiceImpl service;
#Autowired
private ClientRepository repository;
#Test
void someTest() {
//Given
//When
//Then
}
}
But when I run this test I get the following Exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
And this is the cause:
Caused by: java.lang.IllegalStateException: The provided database selection provider differs from the ReactiveNeo4jClient's one.
The thing is I don't use SDN's Reactive features at all in my project. I don't even understand why Spring tries to load it. I've created an Issue under the Spring Data Neo4j GitHub repository (https://github.com/spring-projects/spring-data-neo4j/issues/2488) but they could only tell me that ReactiveNeo4jDataAutoConfiguration gets automatically included if there's a Driver or Flux class in the classpath which I don't have.
I've been debugging the Spring internals while booting up the Application after JUnit Jupiter methods to no success.
What I could see is that at some point after JUnit Jupiter tests preparation/initialization, "reactiveNeo4jTemplate" gets injected into DefaultListableBeanFactory's beanDefinitionNames variable.
I've tried many combinations of different annotations intended to be used when making Integration Tests but the one time it worked was after I explicitly excluded ReactiveNeo4jDataAutoConfiguration class through
#EnableAutoConfiguration(exclude=ReactiveNeo4jDataAutoConfiguration.class)
What I've always seen in some blogposts is that by using #SpringBootTest I shouldn't worry about this kind of problem but it looks like I need to add that annotation every time I want to make a new IT test.
My Integration Tests basically consist of bootstrapping the application + web server (tomcat) along with an embedded Neo4J instance and after that, making requests to check everything works as it should. Do I really need to worry about all of this just to make these simple tests?
Thank you
References:
How do I set up a Spring Data Neo4j integration test with JUnit 5 (in Kotlin)?
SprintBootTest - create only necessary beans
Answering my own question after finding what is causing this error:
In the linked Github Issue, one of the developers says having Flux.class in the classpath forces SDN to instantiate Neo4jReactiveDataAutoConfiguration which is what is causing the other reactive beans to instantiate.
Apparently, neo4j-harness brings io.projectreactor (where Flux.class belongs) as an indirect dependency through neo4j-fabric which is the root of our problems.
The Spring Data Neo4j will be fixing this issue in a patch later this week.

MockMvc remains null [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'd like to perform an integration test. My current approach:
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class)
#AutoConfigureMockMvc
#TestPropertySource(locations = "classpath: application-test.yml")
public class UserControllerIntegrationTest {
#Autowired
MockMvc mockMvc;
#Test
#DisplayName(" sda")
public void test1(){
System.out.println();
}
}
I placed #AutoConfigureMockMvc, but the MockMvc object remains null
I couldn't really understand what was the purpose of such a test, let me explain...
Usually MockMvc is used to test the web layer of the application.
This means that under the hood spring runs "something" that can mimic the requests sent to controllers so that you could check that the annotations are placed correctly, the conversion of objects is done in a proper way, etc. In other words its like testing the controller, but it has nothing to do with services, DAOs, etc. Usually the references to the services from controller can be annotated with #MockBean so that spring will create a stub for services and you'll be able to describe the interactions. Other things like DAOs should never be referenced from controllers anyway (don't them ? ;) ) but in general the same pattern of mocking out these dependencies is applicable here.
Technically its done as follows:
The web mvc test (when annotated properly) doesn't load the whole application context but a "slice" of it - only beans relevant for the web layer.
Now #SpringBootTest annotation does something different. Its designed especially for spring boot application and allows to mimic the whole spring application load. Out of my head (maybe other colleagues will enrich this list), it "adds up" to the regular application context starting:
Properties configuration management
Starters (auto-configuration modules)
Package structure specific scanning for Beans and configurations
Bottom line, it allows starting Spring Boot Test out of some specific configuration or the whole application, it has nothing to do with a web layer only.
So, what I don't understand is what exactly is expected to be tested here.
If your goal is testing a web layer, then you don't have to use Spring Boot annotation (in addition to what I've already explained, spring boot test takes much more time to load)
If your goal is testing the microservice at a whole or sometimes a specific slice of it, then you can use #SpringBootTest` annotation.
If you annotate your test with #RunWith(SpringRunner.class) your mockMvc will not be null.

Run Mongock before #Configuration annotated class

I want to use Mongock migration tool to initialize my app's configuration that is stored in database.
The problem I have is that one of my configs is used in class that is annotated with #Configuration. As Mongock changesets are executed after #Configuration it cannot retrieve not existing yet value from database and that results in a crash of application. Is there a way to postpone creating #Configuration class? Or should I initialize this one config without using mongock?
I don't fully understand your issue. I think that you need Mongock to run before your class annotated with #Configuration is processed. As you mention, SpringMongock requires the configuration class to be processed, as it requires the Spring ApplicationContext. However, you can run Mongock as standalone runner and use it(run it) wherever you want, as it doesn't depend on Spring context.
Mongock documentation
I hope it helps.

Configure Spring Boot in external library

I'm currently code a library in Groovy and I want to use Spring Boot for configuration. That library has no main method.
I've succeeded to launch my unit test by using Spring Boot with the code below:
#RunWith(SpringJUnit4ClassRunner.class)
class AddressTest { ... }
But I want to configure my Address class thanks the application.properties file. For a test, I've only wanted to change the log level while tests by inserting the line below in the application.properties file:
logging.level.root=WARN
But, that doesn't work.
I've tried add the #Configuration annotation in my test class or my tested class but the result is the same.
Thanks for your help.

Injecting spring beans into legacy web app POJOs [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
In order to provide POJOs in my legacy web app (Tomcat 8.0.26) with the ability to send ActiveMQ messages I've taken the recommendation to introduce Camel (2.15.2) / Spring (4.2.1) into the app to purely for the purpose of managing pooled MQ connections. I'm hoping there isn't an easier way.
Doing things the Spring way I'm thinking everything would need to be based around an MVC architecture with HTTP servlet aware controllers having access to the servlet context and therefore the Spring context in order to inject beanFactory beans into classes annotated with #Controller and #Service (and in fact there must be a Spring #Controller class that enables Spring to inject the #Service class.
However, as I've stated this is legacy code that will not be using the spring web framework.
After much pain it seems that the only way I can get beanFactory beans injected into my POJOs is to go the AspectJ and Weaving route. Before I go down this road can someone tell me that this is currently the best approach (what I've read describing this solution is from 2011 Can't get Spring to inject my dependencies - Spring Newbie) ? Can you point me to documentation and a working example?
Many thanks.
1) aspectj with #Configurable
In your #Configuration annotated class/es
you can add some more annotations
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableSpringConfigured
#EnableAspectJAutoProxy
to enable aspectj and the #Configurable annotation,
you need to import the aspectj lib to your project and add the spring tomcat instrumentable java agent in your tomcat lib folder (give a look here, it exaplains how to configure tomcat) http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/instrument/classloading/tomcat/TomcatInstrumentableClassLoader.html
this is not going to help you if you are going to create your pojos using "new"
MyPojo p = new MyPojo(); // no black magic for this, you will need to satisfies the dependencies yourself) but that would be helpful for example when you load some entities through a framework like hibernate and you want to inject something into them.. #Configurable it's an option that can be evaluated in those cases, for what you describe I would rather not use it.
2) You can have some static methods that uses some static set spring-beans and use them from your pojos, something like
class Util{
private static SprintBeanWithJmsSupport x;
public static setSpringBeanToHandleJmsMessages(SprintBeanWithJmsSupport x){
Util.x = x;
}
public static sendJmsMessage(JmsMessage m){
x.sendMessage(m)
}
}
and you can go with Util.sendJmsMessage(...)
this is a bit shitty but it does the work, I don't personally like this approach
3) set your spring beans in your pojo when they need to use them (maybe behind some nice interfaces that suit your domain)
if you go with spring mvc you will likely end up having some controllers that will use some services (generally they handle security / db access and are the entry point to start the "use cases"), as everything wthin these layers is handled by spring it will be very simple to pass the spring-bean to handle jms messaging to your pojos, this seems to me quite a nice way to handle the problem
I went mostly based on memory and something may not be completely accurate, plus my english is .. what it is, so hope this can be helpful anyway.

Resources