I apologize if this ends up being a question... if so could you please add an example to the reference documentation. Since constructor injection is a spring core feature and not a spring boot feature I think this is right place to raise this issue.
Problem
I'd like to inject an ArgumentsProvider
's constructor, but it seems that the ArgumentsProvider
does not have a parameter resolver registered; which is possible now.
import static org.assertj.core.api.Assertions.assertThat;
import com.myorg.dto.CreditCardAccount;
import java.util.stream.Stream;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PerformanceTest {
@ParameterizedTest
@ArgumentsSource(Clients.class)
void testClient(CommonCardAccountRepository repository) {
var referenceId = "0";
var cca = repository.getCreditCardAccount(referenceId);
assertThat(cca)
.isInstanceOf(CreditCardAccount.class)
.hasFieldOrPropertyWithValue("accountReferenceId", referenceId);
}
static class Clients implements ArgumentsProvider {
int port;
@Autowired
Clients(@LocalServerPort int port) {
this.port = port;
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(Arguments.arguments(new CommonCardAccountRepositoryWebClientDefault(port)));
}
}
}
Constructor injecting into the base test is working.
Solution
Spring should fully register the paremeter resolver such that this works in the same way that it does on the constructor for the base test. I don't really know what that means though, or why it doesn't work now.
extended solution
Simply give me a base argument source that can inject the stream of arguments safely with @LocalServerPort
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PerformanceTest {
@ParameterizedTest
@ArgumentsSource(Clients.class)
void testClient(CommonCardAccountRepository repository) {
var referenceId = "0";
var cca = repository.getCreditCardAccount(referenceId);
assertThat(cca)
.isInstanceOf(CreditCardAccount.class)
.hasFieldOrPropertyWithValue("accountReferenceId", referenceId);
}
// assumes that LocalServerPort is somehow injected into CommonCardAccountRepository
static class Clients extends BeanCollectionArgumentsProvider<CommonCardAcountRepository> {}
I'm not certain if this use case is common enough to be worth pursuing, but may be worthy of it's own ticket.
Env
Spring Boot 3.3.7 Java 21
Comment From: sbrannen
I'd like to inject an ArgumentSource constructor but it seems that the ArgumentSource does not have a parameter resolver registered; which is possible now.
That feature was introduced in the recently released JUnit Jupiter 5.12:
- https://github.com/junit-team/junit5/issues/4018
Which version of JUnit Jupiter are you using?