#ContextConfiguration and Security Chain Filter - spring

I'm trying to implement integration testing in my app and have test class like that:
#ExtendWith(value={SpringExtension.class})
#WebAppConfiguration
#ContextConfiguration(classes={AppConfiguration.class,WebMvcConfiguration.class})
public class TestClass{ ... }
inside class i have:
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(SecurityMockMvcConfigurers.springSecurity()).build();
Sadly #Autowired cannot find my Security Spring Chain Filter (or DelegatingFilterProxy) and without it I feel like I won't be able to achievie full functionality of integration testing in spring (espescially the spring-security-test part). In my opinion it's because I initialize my whole app by creating a class that extends AbstractHttpSessionApplicationInitializer. I also feel like adding some sort of custom initializer or loader classes into #ContextConfiguration would help, but acutally have no idea how to do it. Do you guys think it will help and/or can you guys steer me into creating my own loader/initializer?

Related

How to implement Spring Boot service classes without using impl and using a interface as dependency as DIP principle says?

I am trying to implement a Spring Boot REST API but I was asked to use a interface as dependency but no impl, and I don't know how to achieve this. The way I implemented was to have service classes for my entities and there I would just call the repository in my methods. I would like an example of implementation like this.
I watched some youtube tutorials but they all used impl classes
Your controller should have a field of your interface type, with the injecting annotation (in spring it's #Autowired). The DI framework will do the heavy-lifting on startup and inject the correct implementation at runtime
#Controller
public class MyController {
#Autowired
private MyInterface myInterface;
....
}
For this to work, your framework needs to recognize the concrete class. In spring you can achieve this in multiple ways - scanning package paths, xml configuration files and more.
Check the spring documentation to see which way suits you best

Sping-boot configuration-properties and service layer injection

I'm new to spring dependency-injection and am reaching out to learn about best practices. I would like to know if its a good design philosophy to inject classes annotated with #ConfigurationProperties into service layer classes (annotated with #Service). Im trying to map properties in my application.yml to a config-class as follows -
#ConstructorBinding
#ConfigurationProperties(prefix = "application")
class ApplicationConfig(
val kafka: someDeeplyNestedType = SomeDeeplyNestedObj()
) {
// helper functions
}
I'm then injecting above config class in service layer as follows -
#Service
#EnableConfigurationProperties(ApplicationConfig::class)
class RestService(val config: ApplicationConfig) {
init {
// Reference config object
// Reference application.yml properties via config object.
}
}
I'm curious to know if I can improve upon my current implementation - not sure if its agreeable to pass configuration classes to service-layer classes. I'm also curious to know if theres any better approach to wiring ApplicationConfig without needing to use EnableConfigurationProperties annotation.
It is agreeable, documented, and probably "unrivaled" (only bounded by: "limitations" (no SpEL -> helper functions!?;)).
To work with #ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:
#Service
public class MyService {
private final SomeProperties properties;
...
The only problems can arise from the "deeply", not "owning" the (config) structure ...and possibliy from "helper functions".
But
The prefix = "application" "sounds" suspicious!
Note:
[Most - almost All] (official) spring* boot properties, are already "typesafe", and have their object/class representation in spring-boot-autoconfigure packages.
Please study that "typesafe chapter", but also gazing at PropertySource Abstraction.
There is no hard rule for this as in Spring Boot we can add #EnableConfigurationProperties at a class level with stereotype annotations.
As a part of good practices EnableConfigurationProperties or any configuration thing should be part of Configuration class of or main spring boot class so any developer can easily figure out those configuration instead of going any specific service class and then check.
In your case, yo can use #EnableConfigurationProperties annotation in conjunction with #SpringBootApplication annotation.

Springboot build not working because of test configuration

I have started a spring boot project using start.spring.io.
But I am getting this error-
I have read various articles on the internet about this issue and they all say about putting my tests in the same package as my Main class.
But I already have the same.
Could you point out what is wrong with my configuration?
The exception is pretty clear: You are missing a configuration for your spring context. What you need to do is to add the configuration classes for your context like so:
#SpringBootTest(classes = { TestConfiguration.class })
whereas your TestConfiguration class must be annotated with
#Configuration
and/or
#EnableAutoConfiguration
There you can add configurations to your liking. You can of course also use your DatabaseApplication class as Configuration although Im wouldn't recommend that.
The search algorithm works up from the package that contains the test until it finds a #SpringBootApplication or #SpringBootConfiguration annotated class. As long as you’ve structure your code in a sensible way your main configuration is usually found.
Make Sure your DatabaseApplication class is annotated with #SpringBootApplication .

Spring Context Test With Just One Bean

What's the recommended way to run a spring boot test where only the one subject under test is configured in the context.
If I annotate the test with
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = MyTestBean.class)
Then it seems to work - the test passes, the context starts quickly and seems to only contain the bean that I want. However, this seems like an incorrect use of the #ContextConfiguration(classes = MyTestBean.class) annotation. If I understand correctly the class that I reference is supposed to be a Configuration class, not a regular spring service bean or component for example.
Is that right? Or is this indeed a valid way to achieve this goal? I know there are more complex examples like org.springframework.boot.test.autoconfigure.json.JsonTest which use #TypeExcludeFilters(JsonExcludeFilter.class) to control the context - but this seems overkill for my use case. I just want a context with my one bean.
Clarification
I know that I can just construct the one bean I am testing as a POJO without a spring context test and remove the three annotations above. But in my precise use case I am actually reliant on some of the configuration applied to the context by settings in the application-test.properties file - which is why I've made this a Spring Boot test with a profile set. From my perspective this isn't a plain unit test of a single class in isolation of the spring context configuration - the test is reliant on certain configuration being applied (which is currently provided by the spring boot app properties). I can indeed just test the components as a POJO by creating a new instance outside of a spring context, I'm using constructor injection making the providing of necessary dependencies simple but the test does rely on things like the log level (the test actually makes assertions on certain logs being produced) which requires that the log level is set correctly (which is currently being done via logging.level.com.example=DEBUG in a properties file which sets up the spring context).
For starters, reading the documentation first (e.g., the JavaDoc linked below in this answer) is a recommend best practice since it already answers your question.
If I understand correctly the class that I reference is supposed to be
a Configuration class, not a regular spring service bean or
component for example.
Is that right?
No, that's not completely correct.
Classes provided to #ContextConfiguration are typically #Configuration classes, but that is not required.
Here is an excerpt from the JavaDoc for #ContextConfiguration:
Annotated Classes
The term annotated class can refer to any of the following.
A class annotated with #Configuration
A component (i.e., a class annotated with #Component, #Service, #Repository, etc.)
A JSR-330 compliant class that is annotated with javax.inject annotations
Any other class that contains #Bean-methods
Thus you can pass any "annotated class" to #ContextConfiguration.
Or is this indeed a valid way to achieve this goal?
It is in fact a valid way to achieve that goal; however, it is also a bit unusual to load an ApplicationContext that contains a single user bean.
Regards,
Sam (author of the Spring TestContext Framework)
It is definitely a reasonable and normal thing to only test a single class in a unit test.
There is no problem including just one single bean in your test context. Really, a #Configuration is (typically) just a collection of beans. You could hypothetically create a #Configuration class just with MyTestBean, but that would really be unnecessary, as you can accomplish doing the same thing listing your contextual beans with #ContextConfiguration#classes.
However, I do want to point out that for only testing a single bean in a true unit test, best practice ideally leans towards setting up the bean via the constructor and testing the class that way. This is a key reason why the Spring guys recommend using constructor vs. property injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information. This is probably the reason you're getting a weird feeling about setting up the context for the one bean!
You can also use ApplicationContextRunner to create your context using a test configuration of your choice (even with one bean if you like, but as other people have already mentioned for one bean it's more reasonable to use the constructor the classical way without using any spring magic).
What I like this way of testing is the fact that test run very fast since you don't load all the context. This method is best used when the tested bean doesn't have any Autowired dependencies otherwise it's more convenient to use #SpringBootTest.
Below is an example that illustrates the way you can use it to achieve your goal:
class MyTest {
#Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
#Configuraiton
public static class TestConfiguration {
#Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}

How does SimpleCORSFilter work?

How does SimpleCORSFilter work in this example?
Enabling Cross Origin Requests for a RESTful Web Service.
I only see a declaration of SimpleCORSFilter class but no instance. I tried ctrl+f to search the example page but can't find anywhere this class be instantiated.
How does it work?
I am new to Spring and Java.
So more detail more helpful. Thx.
A main point of Spring is a mechanism called dependency injection. Spring allows you to mark your classes, instance variables and so on with special annotations. Spring will look for those annotations and configure your application according to them.
In your example you annotate your filter with #Component:
#Component
public class SimpleCORSFilter implements Filter
And you annotate your Application class with #SpringBootApplication:
#SpringBootApplication
public class Application
The second annotation (#SpringBootApplication) tells Spring to search through your project for #Component annotations. As you annotated your filter with this, Spring will find your filter and instantiate it automatically. That's how your filter will be created and put to the right place.

Resources