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.
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)