Overview
Spring 3.0 added support for JSR-330. However, the spring-test
module is only supporting @Autowired
for dependency injection.
This PR intends to add @Inject
support for spring-test
. Since Spring Framework 6 still supports @javax.inject.Inject
in addition to @jakarta.inject.Inject
, this PR reintroduces support for @javax.inject.Inject
in spring-test
as well.
Examples
The following test passes:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig
public class FooTests {
private final String foo;
@Autowired
public FooTests(String foo) {
this.foo = foo;
}
@Test
public void beanInjected() {
assertThat(this.foo).isEqualTo("foo");
}
@Configuration
static class Config {
@Bean
String foo() {
return "foo";
}
}
}
However, if @Autowired
is replaced with @javax.inject.Inject
the test fails:
package com.example.demo;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig
public class FooTests {
private final String foo;
@Inject
public FooTests(String foo) {
this.foo = foo;
}
@Test
public void beanInjected() {
assertThat(this.foo).isEqualTo("foo");
}
@Configuration
static class Config {
@Bean
String foo() {
return "foo";
}
}
}
Error
org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [java.lang.String foo] in constructor [public com.example.demo.FooTests(java.lang.String)].
Comment From: sbrannen
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Comment From: sbrannen
Hi @FlorianLehmann,
Congratulations on submitting your first PR for the Spring Framework! 👍
However, the
spring-test
module is only supporting@Autowired
for dependency injection.
That's not entirely true.
The Spring TestContext Framework supports whatever DI annotations are supported by AutowiredAnnotationBeanPostProcessor
, which includes @Autowired
and @Value
as well as @jakarta.inject.Inject
and @javax.inject.Inject
(if the latter two are available on the classpath).
Thus, you are free to use @Inject
for fields and methods in your test classes.
The only restriction regarding @Autowired
vs @Inject
is that @Inject
cannot be used for autowiring test class constructors when using JUnit Jupiter (but @Autowired
can).
In addition, @Inject
cannot be used to autowire a particular constructor or method argument simply because @Inject
is configured with @Target({ METHOD, CONSTRUCTOR, FIELD })
. So that limitation is inherent to @Inject
and therefore out of Spring's control.
If I recall correctly, the latter is the reason that we decided not to support @Inject
for JUnit Jupiter features: we wanted to support @Autowired
which can be used consistently for test class constructors as well as individual constructor/method arguments.
However, we will consider adding support for @Inject
for test class constructors, and I have changed the title of this issue to reflect that.
Comment From: FlorianLehmann
Hi @sbrannen,
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Thank you I'll definitely have a look.
In addition,
@Inject
cannot be used to autowire a particular constructor or method argument simply because@Inject
is configured with@Target({ METHOD, CONSTRUCTOR, FIELD })
. So that limitation is inherent to@Inject
and therefore out of Spring's control.
I believe the same limitation applies for "normal" constructor or method arguments. The idea of this PR is to remove the discrepancy between tests and "normal" code when autowiring a constructor using @Inject
.
However, we will consider adding support for
@Inject
for test class constructors, and I have changed the title of this issue to reflect that.
:+1:
Thank you again for your comments.
Comment From: sbrannen
This has been merged into main
in 8dd857a84d7f5d8c7903f445303906c887c70281 and revised in dfea3d05aa4abd0493a2714c0a77edd13a4a2f18, for inclusion in Spring Framework 6.1.
Thanks for your contribution, @FlorianLehmann! 🍃