Testing with spring configuration and Mocking objects - spring

I am using a spring configuration in testing like below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:config/spring/config.xml" })
Let's say I'm testing a service that depends on other services and a repository. Using the #ContextConfiguration these beans will be created and autowired into the service I am testing.
Is it considered better to mock these dependencies and repositories? When creating and loading a test configuration as done currently, a problem in a dependency could cause the test to fail, so I am not really only testing that one service but the other dependencies as well.
Should these dependencies be mocked in the unit test (since you are only supposed to test the functionality of that class and not its dependencies) but instantiated and wired in during integration tests?

Related

How to automate the keycloak setup while running Junit test cases?

I have some Junit test cases in my Spring Boot project. I am using keycloak for getting tokens on the basis of the username and password in order to perform authentication. Now instead of manually deploying the keycloak server while running Junit test cases, I want to automate the keycloak deployment step. I want to ask that is there any Java library through which I can easily start the keycloak, pass the json file that contains all the configuration related to the realm, clients and users and then after running all Junit test cases keycloak automatically stops? Is there any way of doing such thing while running Junit test cases easily?
If you start an external service, this are surely not unit-tests. This is not even integration testing. That's part of end-to-end testing.
With Spring Boot:
the first (unit) are #WebMvcTest (or #WebFluxTest for reactive app) when testing a #Controller or plain JUnit with #ExtendWith(SpringExtension.class) to #EnableMethodSecurity and auto-wire an instrumented instance of the secured #Component (#Service or #Repository with #PreAuthorise, #PostFilter and alike). All external service and all #Components (but the one under test) are mocked and so is the Authentication in the security-context.
the second (integration) are #SpringBootTest which wire together the application #Components (but external services are still mocked / stubbed). It is still possible to #AutoConfigureMockMvc (or #AutoConfigureWebTestClient) and as so, to keep using mocked Authentication.
the last is best to be done without Java (Protractor or whatever end-to-end testing tool)
I answered this subject many times already. To mention a few:
https://stackoverflow.com/a/75465772/619830
How to write unit test for SecurityConfig for spring security
https://stackoverflow.com/a/75376543/619830

Spring integration test has different behaviour when started via IntelliJ run configuration and via mvn verify

I am working on the Spring application based on Spring Boot 2.6.7 (Spring framework version 5.3.19). I noticed that when I run the integration test via IntelliJ run configuration (basically created only by the right clicking on the test method name and choosing Run test) then the same instance of the ApplicationContext is used in the integration test class and in the actual SpringBootApplication which is tested by the integration test.
But when the same integration test is executed from the command line via mvn verify command, then the different instance of the ApplicationContext is active in the Spring Boot Application from the one which is active in the integration test class.
That for example has a consequence that spring data repository which I added as a field to the integration test class with #SpyBean annotation is not not applied in the Spring boot application. In the applicationContext of the integration test class, that spring data repository is registered as a spy but in the application context of the Spring Boot Application there is no spy proxy but the regular repository.
On the other hand when the test is running via IntelliJ run configuration, the applicationContext is same everywhere and the spy bean is active in the Spring Boot Application flow.
So I want to achieve the same behavior when I run mvn verify as I achieve when I run the test from IntelliJ. Any ideas?

Spring Boot Controller IT test not finding class path resources

I have a spring boot web app with both unit tests and IT tests. The application also has a DAL, and I have unit tests in the DAL layer that use an in memory H2 database for tests. The h2 database is created using the same liquibase changelog as my production environment.
The changelogs are packaged in a jar and referenced in my DAL test by adding this to my application.yml file:
liquibase:
change-log: classpath:src/changeLogs/db-changelog-master.xml
This works fine in my DAL project but not in my web project. In my web project I get this error:
Cannot find changelog location: class path resource [src/changeLogs/db-changelog-master.xml]
The test that fails to find the changelog is a Spring Boot IT test. The class under test is a Spring Controller. The test is annotated like this:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles({"IT","development"})
Any ideas what is happening here? Thanks.

Exclude a particular class from Spring Component scan Integration Test

I have a Spring Rest Application built using Spring Boot framework.
Now while writing Spring Integration Test, I wanted to exclude a class
from being get component scanned.my this class contains the dependency for Apache Kafka.
if this class loads while container start up it start looking for Kafka running instances.
so while running Integration test I will not be starting my Kafka server,so I wanted to run
Integration test making Kafka shutdown.
any help is appreciated.
You can exclude the cafka configuration from your test configuration. You haven't shared your code but it would be something like this
#SpringBootApplication(exclude = CafkaConfiguration.class)
public class IntegrationTestConfig {
}
On the other thought you can sure mock the kafka
How can I instanciate a Mock Kafka Topic for junit tests?
The easiest way to do this is to use profiles. In the bean that you only want to be visible to the intergration test add :
#Profile("integration=test")
At the top of the integration test, activate the profile:
#ActiveProfile("integration-test")
Any beans which do not specify a profile (all the other beans) will be present in both test and default profiles. Default is the name of the profile if none is given.

FileNotFoundException in a testing a Maven module

I'm working on a recently mavenized legacy project with following multi-modular structure:
Parent:
Web
Service
Dao
("Service" module is dependent on "Dao" module)
Problem: some tests of Service classes call DAO code that creates beans using Spring's ClassPathXmlApplicationContext (this part is not really DAOs but caching related). Since, ClassPathXmlApplicationContext uses spring config xml of the DAO module - the Service tests fail throwing FileNotFoundException. I think this is because tests run in Service module and the spring config xml being referred lies in Dao module.
Please advise on how can I resolve the above issue in tests referring to code/resources of other modules?
Put a copy of the Spring configuration under src/test/resources in the Service module. Quite often you want a different configuration for testing anyway, but also it means your tests are less dependent on configuration changes in another module.

Resources