'Spring Boot Test: bean not injected
Here my test location:
src/test/java
└── cat
└── gencat
└── catsalut
└── hes
└── mpi
└── unit
└── mapper
└── PatientMapperTest.java
PatientMapperTest.java
is:
@SpringBootTest
@RequiredArgsConstructor
public class Patient {
private final TypesMapper typesMapper;
@Test
void test() {
assertNull(this.typesMapper);
}
}
I've also tried this code (deleting lombok annotation and explicitly initilize typesMapper
field):
@SpringBootTest
public class PatientMapperTest {
private final TypesMapper typesMapper;
public PatientMapperTest(TypesMapper typesMapper) {
this.typesMapper = new TypesMapperImpl();
}
@Test
void test() {
assertNull(this.typesMapper);
}
}
I behaves exactly as before.
Nevertheless, when I perform mvn test
, it seems to be ignored:
$ mvn test
[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors:
[ERROR] PatientMapperTest.test » ParameterResolution No ParameterResolver registered f...
[INFO]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
Related pom dependency:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Any ideas?
Solution 1:[1]
Unlike your production code, where you don't have to annotate your public constructor with @Autowired
, you need it when you want constructor injection for your tests with JUnit 5.
The JUnit Jupiter SpringExtension
(automatically registered with @SpringBootTest
) ensures to resolve any parameter that is annotated with @Autowired
. If you don't add @Autowired
, JUnit doesn't know how to resolve this parameter as no one feels responsible as the Spring extension only kicks in when @Autowired
(or another identifier) is used:
@SpringBootTest
public class PatientMapperTest {
private final TypesMapper typesMapper;
@Autowired
public PatientMapperTest(TypesMapper typesMapper) {
this.typesMapper = typesMapper;
// the original assignment doesn't make sense, why inject the instance and then manually call the constructor?
// this.typesMapper = new TypesMapperImpl();
}
@Test
void test() {
assertNull(this.typesMapper);
}
}
As an alternative, you can also use the @TestConstructor
annotation:
@SpringBootTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
public class PatientMapperTest {
private final TypesMapper typesMapper;
public PatientMapperTest(TypesMapper typesMapper) {
this.typesMapper = typesMapper;
}
}
If you want to dive deeper and understand when the SpringExtension
resolves a parameter from the TestContext, take a look at SpringExtension#supportsParameter
.
You can also safely use field injection for your tests:
@SpringBootTest
public class PatientMapperTest {
@Autowired
private TypesMapper typesMapper;
@Test
void test() {
assertNull(this.typesMapper);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | helle |