How to disable Javers for integration tests? - spring-boot

I am using Javers 3.11.2 with Spring Boot 1.5.17. When I am trying to run integration tests on an embedded database I still see that Javers tables are getting created each time.
Is there a way I can disable Javers during these tests so that these tables will not be created each time?

There is the easy way, put:
javers:
sqlSchemaManagementEnabled: false
in your application-test.yml. See https://javers.org/documentation/spring-boot-integration/

Disclaimer: I've never used Javers.
In general, disabling something in "integration tests" means that you don't want to load some beans (of Javers in this case).
This means in turn that you have to exclude them from the list of configurations spring boot works with.
If you're using javers autoconfiguration module, it has to provide in its own "spring.factories" file (can be found inside the jar) a file for autoconfiguration.
Find its java code and see whether it has some "#Conditional on something (property beans, etc.)" If it has than create a profile for integration test that will configure the beans in a way that conditional in javers won't pass and the bean won't be created as a consequence
If it doesn't have a conditional on something like this, you'll have to exclude the whole configuration. Its usually can be done by annotation #SpringBootApplication(exclude=<JaversAutoconfiguration goes here>
This will, however, turn it off also for production usage, which is obviously not something that you want. So for "production" profile, you'll have to import it as a regular configuration (not an autoconfiguration), for integration test profile you won't need this.

Related

Where should custom validation be placed in spring?

Use case:
At springboot startup I want to validate some thing regarding annotations and application.properties file. So I want spring startup to fail if the rules
are violated.
What is the standard place to do this in Spring?
I have read this article: Baeldung - Article
Two solution that I like:
CommandLineRunner/ApplicationRunner
Registering an ApplicationListener
Are these OK for validating purpose as entry point?
You can create one validator bean and put all different validation logics in different methods and annotate them by #PostConstruct
Unless your configuration is changing frequently,
and it seems likely that it should not change frequently,
you only need to perform this type of validation in an integration test.
Just write a jUnit test that loads the configuration then performs the validation.
These are often, wrongly, called unit tests (because they use jUnit) but are actually integration tests.

Should repositories in Spring Boot applications be tested directly?

Not sure if this will be considered a "legitimate question" or "purely opinion based", but is there a "best practice" with regards to directly testing a repository in a Spring Boot application? Or, should any integration testing simply target the associated service?
The reasoning for the question is simply the fact that, for the most part, a repository in a Spring Boot application contains no project-generated code. At best, it contains project-defined method signatures which Spring generates implementations for (assuming correct naming conventions).
Thanks...
If you can mess it up, you should test it. Here the opportunities to mess up can include:
Custom Queries (using #Query) might be wrong (there can be all kinds of logic mistakes or typos writing a query with no compile-time checking)
Repository methods where the query is derived from the method name might not be what you intended.
Arguments passed in, the type on the parameter list might not match the type needed in the query (nothing enforces this at compile time).
In all these cases you're not testing Spring Data JPA, you're testing the functionality you are implementing using Spring Data JPA.
Cases of using provided methods out of the box, like findOne, findAll, save, etc., where your fingerprints are not on it, don't need testing.
It's easy to test this stuff, and better to find the bugs earlier than later.
Yes, I think is a good pratice to do that. You could use #DataJpaTest annotation, it starts a in memory database. The official documentation says:
You can use the #DataJpaTest annotation to test JPA applications. By default, it configures an in-memory embedded database, scans for #Entity classes, and configures Spring Data JPA repositories. Regular #Component beans are not loaded into the ApplicationContext.
Link to the docs: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
Starting from the idea that repositories should be used only inside services and services are used to interact with the other layers of the system, I would say that testing services should be enough in the majority of cases.
I would not test standard repository methods like findAll, or findBy.., they were tested already and the purpose is not to test JPA, but rather the application.
The only repository methods that should have direct tests are the ones with custom queries. These queries may be located in a shared library and it is not efficient to write similar tests across different projects(in this case regression is a big concern)

#AutoConfigureBefore does not trigger

The intention of this project is to create hooks into Spring Boot's lifecycle, right before Liquibase executes its database schema changesets. The hooks will eventually be used to start / stop a Docker (or Docker-like) container with a Postgres instance. The project must be able to deal with:
tests run from the IDE (IntellIJ, STS)
tests run with Maven Surefire
spring-boot:run
executable JAR
integration test on CI server
Given the above limitations, the best approach appeared to be to have an Auto-Configuration and instructing it to run before Liquibase.
The Auto-Configuration class has been annotated:
#ConditionalOnProperty(prefix = "docker_42",
name = "enabled", matchIfMissing = false)
#AutoConfigureBefore({LiquibaseAutoConfiguration.class })
public class Docker42AutoConfiguration {
spring.factories has a single entry:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
nl._42.autoconfig.Docker42AutoConfiguration
The entire (stripped down) project can be found here: https://github.com/robert-bor/auto-configuration-question
The results can be verified by either:
setting up the project in your IDE & running a test, or
executing spring-boot:run
In Spring Boot's log you will see Liquibase executing before the custom AutoConfiguration.
Note that various other routes have been tried (ApplicationListener, RunListener), but none played nice with all the required in-roads.
Pointers as to why #AutoConfigureBefore does not work in my project would be very much appreciated.
You're trying to apply a configuration semantic to some runtime constraints. Auto-configuration is about providing bean definitions in the context, something that will ultimately create bean instances that you can wire in your components.
Assume that you need bean Foo in order to auto-configure something. You need to make sure that FooAutoConfiguration runs before yours so that the context has a chance to contain a bean definition for Foo. That is explained in quite details in our last Devoxx university.
The documentation you referenced in that comment does not imply runtime constraints in any way:
Hint for that an auto-configuration should be applied before other specified auto-configuration classes.
applying the auto-configuration does not mean that the beans created by that configuration will effectively start before the beans created by another configuration. In other words, what you've done is making sure that your auto-configuration configures the context before the liquibase auto-configuration has a chance to do so. It does not imply, in any way, that the beans that will be created (we're not there yet) will be created in that order.
If that's what you want to do and you have no bean dependency, you can just forget about all that and create a bean lifecycle dependency instead. It can be tricky because liquibase may or may not be there but we essentially do that for Hazelcast (see the auto-configuration). Basically we need to make sure that Hazelcast is started before the JPA container is started in case it wants to use Hazelcast as second level cache.

Programmatically configure Spring Boot app

what's the easiest way to get the spring boot goodness but not try to autoconfigure all the things? For instance, to only run flyway with our already configured properties (some loaded via Consul + Spring Cloud), I was hoping I could do something like:
#Configuration
#Import({DataSourceAutoConfiguration.class, FlywayAutoConfiguration.class})
public class FlywaySetup {}
and have the main method just call SpringApplication.run(FlywaySetup.class)
The problem with this is it picks up all the Component Scan / crazy long list of other dependencies. Any way to specifically configure the dependencies (but still get the nicities of the framework)
If you run this app, it shouldn't use component scan at all. There's nothing that triggers component scan in spring boot besides #ComponentScan (that's available on #SpringBootApplication).
It would help if you could provide more accurate details rather than "crazy long list of other dependencies.". Running that FlywaySetup should only load those two configuration classes (important: these are not handled as auto-configuration anymore). If you have component scan, there's something else you're not showing.
You can exclude auto-configurations you don't need.
You may want to take a look at this SO answer to explore mechanism how to do that.

Good strategy for Spring Framework end-to-end testing

So this is a rather "big" question, but what I'm trying to accomplish is the following:
I have a Spring application, MVC, JDBC (MySQL) and JSP running on tomcat.
My objective is to test the entire "stack" using a proper method.
What I have so far is Junit using Selenium to simulate an actual user interacting with the application (requires a dummy account for that), and performing different validations such as, see if element is present in the page, see if the database has a specific value or if a value matches the database.
1st concern is that this is actually using the database so it's hard to test certain scenarios. I would really like to be able to mock the database. Have it emulate specific account configs, data states etc
2nd concern is that given the fact that I use what is in the database, and data is continuously changing, it is hard to predict behavior, and therefore properly asserting
I looked at Spring Test but it allows for testing outside a servlet container, so no JSP and no Javascript testing possible.
I saw DBUtils documentation but not sure if it will help me in this case
So, to my fellow developers, I would like to ask for tips to:
Run selenium tests on top of a mocked database
Allow different configs per test
Keep compatibility with Maven/Gradle
I have started with an ordered autowire feature to support this kind of stubbing.
It's basically an idea that i took over from the Seam framework i was working with in the past but i couldnt find yet a similar thing in spring.
The idea is to have a precedence annotation (fw, app,mock,...) that will be used to resolve the current implementation of an autowired bean. This is easy already in xml but not with java config.
So we have our normal repository beans in with app precedence and a test package stubbing these classes with mock precedence.
If both are in the classpath spring would normally fail with a duplicate bean found exception. In our case the extended beanfactory simply takes the bean with the highest precedence.
Im not sure if the order annotation of spring could be used directly but i prefered to have "well defined" precedence scopes anyway, so it will be clear for our developers what this is about.
! While this is a nice approach to stub so beans for testing i would not use it to replace a database definition but rather go with an inmemory database like hsql, like some previous answers mentionned already. !

Resources