Как работает @Autowire в модульном тесте с пружинной загрузкой? - PullRequest
0 голосов
/ 05 ноября 2019

Мне было интересно, как здесь работает @autowire?

Я пытаюсь попрактиковаться в использовании mock для проведения модульного теста в Spring.

Вот код для моего простого UserService

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    public User findByName(String name) {

        return userRepository.findByName(name);
    }
}

Вот код для моего модульного теста.

package com.geotab.dna.springtestdemo.services;

import com.geotab.dna.springtestdemo.entities.User;
import com.geotab.dna.springtestdemo.repositories.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
public class UserServiceTest {

    @TestConfiguration
    static class UserServiceImplContextConfiguration {

        @Bean
        public UserService userService() {
            UserService userService = new UserService();
            return userService;
        }
    }

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void whenFindByName_thenReturnUser() {

        //given
        String name = "alex";
        User user = new User(name);
        Mockito.when(userRepository.findByName(name)).thenReturn(user);

        //when
        User found = userService.findByName("alex");

        //then
        assert (user.getName().equals(found.getName()));
    }
}

Я получил вышеуказанный код из блога, он работает. Но меня смущает то, почему UserRepository может быть внедрен в UserService? Потому что в самом начале я думаю, что UserService.UserRepository будет нулевым.

1 Ответ

2 голосов
/ 06 ноября 2019

Просто посмотрите на разные части программы, какие у вас есть

  1. @RunWith(SpringRunner.class) вы используете класс бегуна, предоставляемый Spring
  2. @Autowire, который делает поиск весны длякласс в контексте его приложения, когда он заключает в себе это утверждение.

Теперь перейдем к вопросу, как объект userRepository внедряется в userService. Это из-за @MockBean. Из документации написано

Аннотация, которую можно использовать для добавления макетов в Spring ApplicationContext. Может использоваться как аннотация уровня класса или для полей либо в классах @Configuration, либо в тестовых классах, которые являются @RunWith SpringRunner.

Это означает, что когда Spring встречает @MockBean, он добавляет этот компонент кконтекст приложения. Следовательно, когда он встречает @Autowired в userRepository внутри userService, он внедряет имитируемый экземпляр, который у него есть.
Эта аннотация была представлена ​​в нескольких выпусках назад. Перед этим мы должны были объявить макет с помощью @Mock и использовать @InjectMocks или с помощью инъекции конструкции.

Посмотрите на этот вопрос , чтобы узнать больше о различиях между @Mock и @MockBean

...