I have a common spring boot application consisting of a controller and a service layer. A database is not involved as I use another rest api to store the data.
Now I want to the my controller and therefor I want to mock my sevice partially. Partially because I have one method in it that takes a dto and converts it to my business model. I know this can also be solved with a constructor of the bussiness model but anyway I came to the following problem:
CODE
Controller
@RestController
public class RegistrationController {
@Autowired
private UserRegistrationService userRegistrationService;
@PostMapping(value = "/user", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserId> createUser(@RequestBody @Valid UserDto userDto) {
KeycloakUserRepresentation keycloakUserRepresentation = userRegistrationService.convertUserDtoToKeycloakUserRepresentation(userDto);
UserId userId = userRegistrationService.createNewUser(keycloakUserRepresentation);
return new ResponseEntity<>(userId,HttpStatus.CREATED);
}
TEST
@SpringBootTest
@AutoConfigureMockMvc
@ExtendWith({RestDocumentationExtension.class})
@AutoConfigureRestDocs
class RegistrationControllerRegistrationTest {
private static final UserDto testUsertDto = new UserDto();
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Spy
private UserRegistrationServiceImpl userRegistrationService;
In my test method I define:
doReturn(testUserId).when(userRegistrationService).createNewUser(any(KeycloakUserRepresentation.class));
PROBLEM:
I expect that while not define a doSomething in my test, the conversion of the userDto to a keycloak representation is done by the original method. This seems to work as when I debug in my Controller the keycloakUserRepresentation has the correct values. The problem is that in the next step the
createNewUser
method is not stubbed/mocked. The original method is executed and so my test fails. What I want is that when I provide a doSomething method in my testcase, I want the original method to be mocked.
It worked because the bean wasn't spied on at all. Although
@Spy
may help in creating a mocked object, it does not result in a mocked Spring bean in your test application context. Use@SpyBean
to have Mockito spy on a bean in the Spring application context.