Run junit without data source persistence context in spring boot - java

In my spring boot application, there is a persistent context class for data source connectivity. While I write junit for this application, it always call this configuration class and fails when database connection is off. The junit didn't run if I exclude this configuration class. What is the solution to run the junit,even the database connectivity fails.

Related

Spring Boot: how to run a server at Spring Context startup and stop it during context shutdown during execution of tests?

My Spring Boot application uses a database server. During the tests, I would like to run an embedded version of the database. The server starts with a random port each time (it's from testcontainers.org).
First thing I tried was to use JUnit4's #ClassRule to start/stop the server, but Spring Boot is smart and re-uses contexts across test classes. So for a single test class everything works fine, but when I run tests in a package (or all tests), they fail due to this lifecycle difference.
Is it possible to somehow hook into tests execution and get a callback when Spring Boot Test infrastructure starts and stops a new context?
The most probable answer I will get is 'just add a server bean to the context when your tests run'. Ok, but here I face another problem:
How do I make sure that the server bean is initialized before other beans that talk to the server? #DependsOn does not seem to fit here as I do not want to have in production a bean annotated with #DependsOn("testServer")
Spring Boot is 2.1.6.

Integration tests of Spring application

I am trying to implement integration tests for my Tomcat application, but my issue is that the application is launched separately from the tests so the tests cannot access the application context and neither the database.
My idea is running the tests "within" the running application, so I can #Autowire EntityManager and check for instance the state of the database during testing or even create database entities for testing.
My only idea of doing this is to actually run the application programmatically from the tests as ClassPathXmlApplicationContext("applicationContext.xml") and the access the Context. This would work, but it would be very hard for debugging as we wouldn't be able to use Hotswapping during the testing. Also I guess the server would be stopped as soon as the tests would end. I guess that is not the best and correct solution.
EDIT:
My question was probably unclear, so I will try to clarify.
I have a Tomcat application with Spring and Hibernate. The Spring beans and Hibernate database connection is initialised when the Tomcat application is started. The issue is how to run the tests of the active Spring beans from methods annotated with #Test in src/test/java which are started separately.
Consider this class:
#Component
class MyRepository {
#Autowired
EntityManager em;
#Transactional
public void myMethod(MyEntity entity) {
// do some job with entity
...
em.flush();
}
}
This class will be initialised with Tomcat as a MyRepository bean.
To test it, I cannot just call new MyRepository().myMethod(...) - I need to access the bean. The issue is accessing the bean from the #Test method:
#Test
void testMyRepository() {
Item item = ...
// then use the repository to handle the entity
context.getBean(MyRepository.class).myMethod(item);
// then assert the state of the database
context.getBean(EntityManager.class).find(Item.class, ...) ...
}
I can probably get the context in the initialisation of the tests with
ApplicationContext context = ClassPathXmlApplicationContext("applicationContext.xml");
But it would mean launching the whole application each time the tests are started. The better solution would be if the application could run separately from the tests.
Hope my problem is more clear now.
I would suggest you to use the SpringRunner to start the Spring application context and perform your tests on that running instance. You can customize the context the way it doesn't contain parts you don't want to tests and you can create mocks for components that require some external resources (REST clients and such). Take a look at the Spring docs or Spring Boot docs.
If multiple tests use the same Spring context configuration, the context is started just once and reused. So it's good to have it's configuration in a parent class of your tests. You can autowire any Spring bean into your test and test it.
You can use an in-memory database (such as H2) instead of a production one, so your tests are not dependent on an external infrastructure. To initialize the database, use tools like Flyway or Liquibase. To clear the database before each test, you can use the #Sql annotation.
You can find many examples of projects with such tests, for example my own demo.
If you want to test an external system, I would suggest something like JMeter.
Unfortunately you cant mirror your classes and use them in your tests. Thats a big disadvantage of web services. They always depend on user / machine interaction. With a lot of effort you can extract the functionality of the essential classes or methods and construct test scenarios etc. with jUnit.
The Overview of your possibilities:
special drivers and placeholders
you can use a logger with detailed log-level and file output. Then you created scenarios with the expected result and compare it with your log files.
Capture replay tools. They record your exection and replay them for monitoring.
I can also recommend using Selenium for the frontend tests.
Hope it helped.

Run a SQL script in spring-test root startup

I have a spring project, and I am doing unit testing of my project with spring-test in a PostgreSQL database for the test (I have a database for test and another for development). And I want to initialize my database with a SQL script in the startup (root) of all tests.
I need some direction, I found "flyway" but first I am looking for something with basic spring or something like that or any idea. Thanks
To initialize an existing (i.e., normally _external) database when the Spring ApplicationContext starts, you can either use the jbbc namespace in XML or a DataSourceInitializer with JavaConfig.
See Initializing a database using Spring XML and DataSourceInitializer for details.
there is simple implementation from spring side
all we need is just add line below
ScriptUtils.executeSqlScript(connection, new
ClassPathResource("DB_structures_Creation.sql"));
This implementation by default will uses H2 and will create all the tables and other stuff except pl-sql ones

How execute `schema.sql` during spring boot test without embeded datasource configuration?

There is spring boot application with h2 database which is used as primary database. Also there is a resource/schema.sql wich is loaded at startup by spring boot.
But during integration tests with #SpringBootTest spring boot does not load this schema.sql. Instead it requires to setup embeded database while there is h2 db already.
Is there a way to execute schema.sql without embeded datasource configuration? And do it only once for all tests (e.g. using #Sql for schema creation for all test is not a solution)?
Annotate your class or method with #Sql(scripts = "classpath:schema.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) where your schema.sql is on resources folder.
You need this if your tests are marked as integration tests. Spring boot will do this for you if you are running a unit test or just compiling with unit tests enabled which is the default.
Set this in your properties file and then rename schema.sql to schema-test.sql
spring.datasource.platform=test
Spring boot automatically configures the embedded database for you as long as you have the it in the classpath (h2, hsqldb or derby)

Spring Boot : Integration Test not excluding my Application configuration class

I have an application which connects to a zookeeper to perform operations on HBase. However, for Integration Tests, I have a class to create in-memory tables, and perform tests without trying to connect to said zookeeper.
I have defined a IntegrationTestAppConfig.class as follows:
#EnableAutoConfiguration(exclude = { AppConfig.class})
#ComponentScan
#Configuration
#EnableAsync
public class IntegrationTestAppConfig{
..... //this is where I create a bean for my HBaseConnectionManager to use my in-memory table environment
}
And, in my integration test class, I have the following:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = IntegrationTestAppConfig.class)
public class AHCLIManagerIT {
#Test
.....
}
Based on what I've read from the Spring-boot documentation, the integration test class should use IntegrationTestAppConfig.class for the application configuration.
However, when I run the Integration Test, I get an error saying connection to zookeeper timed out. In the stack trace, I see that the error occurred in AppConfig.java (my main class for app configuration), where it tries to create a HBaseConnection to the zookeeper.
I don't understand why my application is not using the App config class that I've defined in the annotations.
Is your AopConfig class actually an autoconfiguration class? Autoconfiguration classes are loaded by naming them in a spring.factories file in META-INF. The exclude attribute would only apply to those I believe. Auto configuration happens after regular app configuration anyways.
Also you have #ComponentScan on your config. If you really need to exclude AopConfig that would be the annotation I'd expect it to be on.
Though IMHO something doesn't seem right for doing a component scan in your tests

Categories