Как внедрить интерфейс в Spring Boot Controller Test? - PullRequest
0 голосов
/ 28 сентября 2019

Я создал проект Spring Boot с RestController.Я ищу, чтобы проверить RestController в SpringBoot.Но я не могу ввести интерфейс в Spring Controller Test.Я получаю сообщение об ошибке ниже.

Пожалуйста, помогите.

    Cannot instantiate @InjectMocks field named 'authService'! Cause: the type 'AuthService' is an interface.
You haven't provided the instance at field declaration so I tried to construct the instance.
Examples of correct usage of @InjectMocks:
   @InjectMocks Service service = new Service();
   @InjectMocks Service service;
   //and... don't forget about some @Mocks for injection :)

Мой исходный код выглядит следующим образом

Интерфейс AuthService

public interface AuthService {

    AppUser save(RegisterDto registerDto);
}

AuthServiceImpl.java

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AppUserRepository userRepository;

    @Override
    public AppUser save(RegisterDto registerDto) {
        if (userRepository.existsByUsername(registerDto.getUsername())) {
            throw new RuntimeException("Username already taken");
        }

        if (userRepository.existsByEmail(registerDto.getEmail())) {
            throw new RuntimeException("Email address already registered");
        }
        AppUser user = convertToAppUser(registerDto);
        return userRepository.save(user);
    }

    private AppUser convertToAppUser(RegisterDto registerDto) {
        AppUser user = new AppUser(
                registerDto.getFirstName(),
                registerDto.getLastName(),
                registerDto.getUsername(),
                registerDto.getEmail(),
                registerDto.getPassword());
        return user;
    }
}

AuthController.java

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private AuthService authService;

    @PostMapping("/users")
    public AppUser save(@RequestBody RegisterDto registerDto) {
        return authService.save(registerDto);
    }
}

AuthControllerTest.java

@RunWith(SpringRunner.class)
@WebMvcTest(AuthController.class)
public class AuthControllerTest {

    @Autowired
    MockMvc mockMvc;

    @InjectMocks
    private AuthService authService;

    @Test
    public void save_user__success() throws Exception {
        AppUser user = new AppUser("admin", "admin", "admin", "admin@gmail.com", "admin");

        when(authService.save(Mockito.any(RegisterDto.class))).thenReturn(user);

        mockMvc.perform(
                MockMvcRequestBuilders.post("/api/auth/users")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(convertToJson(user)))
                .andExpect(status().isCreated());
    }


    /*
     * converts a Java object into JSON representation
     */
    public static String convertToJson(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

1 Ответ

1 голос
/ 28 сентября 2019

Вы бы использовали @InjectMocks только в конкретном экземпляре объекта класса (реальную функциональность которого вы хотите использовать, только с его поддельными зависимостями), а не в интерфейсе (который обычно не имеет функциональности, просто контракт илиэкземпляр).

Поскольку вы используете when(authService.save(...))).thenReturn(...), то, на мой взгляд, вы хотите на самом деле @MockBean, поэтому используйте его вместо @InjectMocks:

@RunWith(SpringRunner.class)
@WebMvcTest(AuthController.class)
public class AuthControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean // replaced @InjectMocks
    private AuthService authService;

    @Test
    public void save_user__success() throws Exception {
        AppUser user = new AppUser("admin", "admin", "admin", "admin@gmail.com", "admin");

        when(authService.save(Mockito.any(RegisterDto.class))).thenReturn(user);

        mockMvc.perform(
            // ...
...