1

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?

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • This error does not mean that your bean is not injected it is something else. Kindly see https://stackoverflow.com/questions/51867650/junit-5-no-parameterresolver-registered-for-parameter – JCompetence Dec 16 '21 at 10:59
  • 1
    Does it work if you annotate the constructor argument with `@Autowired`? – Henning Dec 16 '21 at 13:59

2 Answers2

2

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);
        }
    
    }
helle
  • 11,183
  • 9
  • 56
  • 83
rieckpil
  • 10,470
  • 3
  • 32
  • 56
1

First you should register beans in test configuration file that you want to use and than inject them.

@TestConfiguration
public class TestBeans {
    @Bean
    TypesMapper typesMapper(TypesMapper typesMapper){
        return typesMapper;
    }
}

After registering you use them.

@SpringBootTest
@Import(TestBeans.class)
public class Patient {
    @Autowired
    private TypesMapper typesMapper;

    @Test
    void test() {
        assertNull(this.typesMapper);
    }
}

or with with constructor injection.

Abdugani
  • 11
  • 1