Reputation: 41
I am trying to load, in a test of a Spring Boot (v2.3.8) application, only named components in a basic Spring application-context. More specifically, I want to load, in a test, a Spring application-context that configures at least logging, loading of external properties, validation (through Java Validation API), and @Value
-plugging but without MVC, Data JPA, etc. In essence, I want to test, through a constraint-annotated interface (e.g. @NotBlank
), a @Service
that exercises only the local file-system (no MVC, Data JPA, or any other Spring Boot Test "slice") and has one data-member populated through @Value
.
I have tried, to no avail, many annotations (and some of their inherent attributes), in different combination-subsets: e.g. @SpringBootTest
, @Configuration
, @ContextConfiguration
, @TestConfiguration
, @TypeExcludeFilters
, etc. For example:
@Validated
public interface SomeService {
String someMethod (@NotBlank String someParam);
}
...
@Service
public class SomeServiceImpl implements SomeService {
@Value("${some.value}")
private String someValue;
@Override
public String someMethod(String someParam) {
// do something with local file-system,
// with someValue in hand, and
// knowing someParam not blank
}
}
...
@SpringBootTest(classes={SomeServiceImpl.class},webEnvironment=WebEnvironment.NONE)
class SomeServiceTests {
@Autowired
private SomeService someService;
@Test
void throwConstraintViolationException_whenSomeParamNil() {
assertThrows(
ConstraintViolationException.class,
()->someService.someMethod(new String()));
}
...
}
In this example, attribute classes
of @SpringBootTest
loads the cited class but obscures all of the basics (logging, validation, etc.) that I'm also seeking.
The following excerpt, from Craig Walls' "Spring Boot in Action," seems to be exactly what I'm seeking, but its main tool (@SpringApplicationConfiguration
) is now deprecated (and its officially-recommended replacement - @SpringBootTest
- does NOT behave equally, at least regarding attribute classes
):
Although @ContextConfiguration does a great job of loading the Spring application context, it doesn’t load it with the full Spring Boot treatment...SpringApplication not only loads the application context, but also enables logging, the loading of external properties (application.properties or application.yml), and other features of Spring Boot. If you’re using @ContextConfiguration, you won’t get those features. To get those features back in your integration tests, you can swap out @ContextConfiguration for Spring Boot’s @SpringApplicationConfiguration:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=AddressBookConfiguration.class)
public class AddressServiceTests {
...
}
There, he gets the "full Spring Boot treatment" but adding only the class (@Service
) he cites (not every @Component
, @Controller
, and @Repository
of his domain).
How to do this today, without deprecated @SpringApplicationConfiguration
?
I originally stated that my (not Craig Walls') example (namely @SpringBootTest(classes={SomeServiceImpl.class},webEnvironment=WebEnvironment.NONE)
, although it loaded the cited class, obscured all of the basics of an application-context that Spring Boot would normally load. Through further experimentation, I have found that that statement was inaccurate, in that not all but, only, some of the basics are obscured, namely validation (implementation of Java Validation API). In other words, logging, loading of external properties, and @Value-plugging are, indeed, loaded/configured. I think that I must've gotten confused, in all of my many permutations/attempts.
Upvotes: 2
Views: 3748
Reputation: 41
After yet more experimentation, I've found an answer. I can't say whether it's the best answer, but it's concise and certainly does the trick...
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
// automatically configures validation (implementation of Java Validation API)
@ImportAutoConfiguration(ValidationAutoConfiguration.class)
// obscures/disables any otherwise-automatic web-environment;
// automatically configures logging, loading of external properties, and @Value-plugging;
// and, beyond that, adds to application-context only _cited_ classes/configuration-classes
@SpringBootTest(classes={SomeServiceImpl.class},webEnvironment=WebEnvironment.NONE)// full context loaded, if unqualified
public class SomeServiceTests {
...
}
Upvotes: 1