Модульное тестирование сервисного уровня Spring Boot с помощью Mockito - проверенные данные обнуляются - PullRequest
0 голосов
/ 02 марта 2019

Я пытаюсь протестировать слой сервиса, используя Mockito с JUnit, но каждый раз, когда я запускаю его, возвращаемый объект обнуляется.

Дополнительная информация:

  • UserRepository - простая пружинаРасширение репозитория данных CRUDRepository.
  • Пользователь - простая сущность JPA.

и тест:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService = new UserService();

    private User user;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void tesGetUserIdStatus() {

        // given
        user = new User();
        user.setUserName(userName);
        user.setUserId(userId);

        User newUser = new User();

        // when
        Mockito.when(userRepository.findByUserId(userId)).thenReturn(newUser);
        User result = userService.getUserById(user);

        // then
        Assert.assertEquals(newUser, user);
    }

}

Этот тест завершится тем, что ожидаемые значения объекта будут обнуленыкогда фактические значения верны.

Служебная часть, которую я хочу проверить, выглядит следующим образом:

@Component
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
    this.userRepository = userRepository;
}

    public User getUserById(User user) throws EntityNotFoundException {


        String userId = user.getUserId();

        user = userRepository.findByUserId(userId);

        return user;
    }
...

Ответы [ 3 ]

0 голосов
/ 02 марта 2019

В вашем тесте есть несколько проблем:

  • UserService создается Mockito (@InjectMocks) - не инициализируйте его с новым экземпляром UserService - вот причинавы получаете NPE
  • , так как вы используете MockitoJUnitRunner, вам не нужно явно звонить MockitoAnnotations.initMocks
  • when(userRepository.findByUserId(UserId)) - что вызывает UserId?
  • Mockito.when() должен быть частью данного раздела
  • , в разделе then вам следует утверждать значение, которое вы получили в разделе when
0 голосов
/ 02 марта 2019

Я вижу, что есть проблема с дизайном в дополнение к неподходящему пользователю mockito.@InjectMocks не очень хороший выбор.Его реализация имеет недостатки, вот что говорят их javadoc.

  • Mockito будет пытаться внедрить mock только путем инжекции в конструктор, * инжекцией в сеттер или в свойство, как описано ниже.* Если любая из следующих стратегий потерпит неудачу, Mockito не сообщит о неудаче ;* т.е. вы должны будете сами предоставить зависимости.

Я думаю, что это следует считать устаревшим, чтобы разработчики могли красиво внедрить конструктор.Взгляните на этот подход;

Рефакторинг UserService, чтобы вы могли внедрить UserRepository через UserService конструктор .Например: https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html

Тогда

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;


    private UserService userService;
    private User user;

    @Before
    public void setUp() throws Exception {
       userService = new UserService(userRepository);
    }

    @Test
    public void tesGetUserIdStatus() {
        //your test code
    }

Это хорошая практика, и вы можете проверить свою логику (услуги, помощники и т. Д.) Изолированно с правильными насмешками и заглушкой.

Однако, если вы хотите проверить правильность внедрения ресурсов с помощью контейнера Spring ioc и хотите выполнять такие операции, как проверка, вам следует подумать о правильных загрузочных тестах Spring / Spring.Посмотрите официальные документы по весеннему тестированию - https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

0 голосов
/ 02 марта 2019

Под findByUserId(UserId) вы имеете в виду findByUserId(userId), а под Assert.assertEquals(newUser, user) вы имеете в виду Assert.assertEquals(result, user)?И откуда берутся значения userName и userId?

И, пожалуйста, не используйте @InjectMocks для внедрения UserService

, попробуйте вместо этого:

@Autowired
private UserService userService;

или хотя бы

@InjectMock
private UserService userService;

Вашпроверка может завершиться неудачно, поскольку репозиторий внутри UserService не может быть введен должным образом, и возвращаемый результат будет null .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...