12

I created a Spring Boot Java library which has a set of utilities that perform certain functions. This library can then be used across multiple applications that require its utilities. This library was designed as a Spring Boot application to allow these utilities to be injected in the application context.

Now I wish to execute a JUnit test on one of the utilities to ensure it is working correctly. However, since this application is basically a collection of utilities and not a stand-alone application, it does not have a main class or the main method annotated with @SpringBootApplication. Now, when I run the JUnit test, it comes up with an error.

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) 

Is it possible to test this Java library, or should we write the test cases only in the application that will be using this library?

2
  • I don’t think so. If it’s just a library, you can only run unit tests. Integration tests is application responsibility. Or you can create a demo application that uses your code and is a spring boot app specific to your code and write integration tests there. Commented Dec 10, 2019 at 4:25
  • Look at spring.factories that Bramnik mentioned. See this answer ->stackoverflow.com/questions/32107610/… and this blog blog.pchudzik.com/201903/spring-factories Commented Dec 10, 2019 at 6:21

1 Answer 1

12

I think there is some contradiction in what you say:

  1. Created a Library...that was designed as a Spring Boot Application.
  2. Library can be used across multiple applications that require its utilities.

If you implement "1" then there is a module with spring boot maven/gradle plugin configured to create a JAR of the application which is a library.

But if you have, say, module X that wishes to use your library, its impossible to add the dependency on your library in this module, spring boot JAR artifacts are not JARs in a Java Sense... So this won't work in both IDE and maven (I mean technically you'll have compilation errors).

Then you write something that completely makes sense: You say that the library by itself doesn't have a main class/@SpringBootApplication annotated class. From this I conclude that its not a spring boot application, but rather a spring boot starter module.

In this case you should not use @SpringBootTest annotation since it mimics the way of starting up the spring boot application (finds main class, scans the packages according to the package structure, loads the configurations and so forth). You don't need all this. Well, maybe technically you can still create a main class annotated with @SpringBootApplication and put it into src/test/java/.../ in a relevant package, but it doesn't really makes sense.

So basically you have two choices:

  1. You can test the utilities without spring at all as if the utility is just a Java class, mock the dependency with Mockito and you're good to go. Since these tests are fast, it you be the best option.

  2. You can run the integartion test by means of loading the spring context with all the required beans created by the application.

 @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {MyLibraryConfiguration.class}) public class SampleLibraryTest { @Autowired private SomeBeanFromTheLibrary theBean; @Test public void testFoo() { .... } } 

Now although you can use component scanning (in this case you'll need slightly different annotations), in the example I've assumed that you're using java config, register all the beans of the library there and create a spring.factories that uses this Java Configuration file to create an autoconfiguration (you add a dependency on the library in module X and it loads the beans defined in the library automatically).

This @ExtendsWith (@RunWith for junit 4) has nothing to do with Spring Boot, it behaves as a "plain" spring, you can autowire beans, create mock beans, there is caching of configurations, etc.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the detailed explanation. In my example, I'm actually using component scanning. Could you please explain which annotations that would change for this?
But since your library is meant to be integrated with Spring boot anyway, I think Java Configuration will be a better choice. Spring boot app (module X) might not enable the component scan on your packages, by spring boot convention for starters you should write an autoconfiguration really...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.