I’m trying to test a Spring Boot controller using MockMvc, as follows:
@WebMvcTest(MyController.class)
public class MyControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserRepository userRepository;
@Test
void getUser() throws Exception {
when(myRepository.findByEmail("[email protected]"))
.thenReturn(Optional.ofNullable(
User.builder().email("[email protected]").id(12).build())
);
mockMvc.perform(get("/user/12"))
.andExpect(status().isOk())
.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.