@WebMvcTest with MockMvc — how to get MapStruct mapper bean instantiated and injected?

I’m trying to test a Spring Boot controller using MockMvc, as follows:

public class MyControllerTest {

    @Autowired private MockMvc mockMvc;

    @MockBean private UserRepository userRepository;

    void getUser() throws Exception {
        when(myRepository.findByEmail("[email protected]"))
                        User.builder().email("[email protected]").id(12).build())

                .andExpect(jsonPath("$.email").value("[email protected]"));

Now, the controller uses a MapStruct mapper which is injected. Its definition:

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
public interface UserMapper {
    User toEntity(UserDto userDto);

    UserDto toDto(User user);

    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    User partialUpdate(UserDto userDto, @MappingTarget User user);

When I run this test, I get:

No qualifying bean of type ‘com.mycompany.myproject.mappers.UserMapper’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

How can I get this bean injected so that it can be picked up by the controller?

@WebMvcTest(MyController.class) adds only MyController to the application context and excludes all other beans.
You want to add at least @Import(UserMapper.class) plus any other beans your test requires to be in the application context.
If you don’t require the real bean but want to mock it instead, add a field @MockBean UserMapper userMapper to your test class.

Read the relevant section from the @WebMvcTest JavaDoc:

Typically @WebMvcTest is used in combination with @MockBean or @Import to create any collaborators required by your @Controller beans.

Leave a Comment