аннотации @Mock и @InjectMocks не работают - PullRequest
0 голосов
/ 03 августа 2020
  • остальное
@RestController
public class StackOverFlowController {


    private StackOverFlowService service;

    @Autowired
    public StackOverFlowController(
            @Qualifier(value = "stackOverFlowServiceImpl")
            StackOverFlowService service) {
        this.service = service;
    }

    @RequestMapping("api/stackoverflow")
    public List<StackOverFlowDto> getListOfProviders() throws URISyntaxException {

        List<StackOverFlowDto> allSites = service.getAllSites();

        return allSites;
    }
}
  • сервис
public interface StackOverFlowService {
    List<StackOverFlowDto> getAllSites() throws URISyntaxException;

    List<StackOverFlowDto> getAllSitesByTitle(String title) throws URISyntaxException;
}
  • пом. xml
 <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${version.mapstruct}</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • test
@RunWith(MockitoJUnitRunner.class)
public class StackOverFlowControllerTest {

    @Mock
    private StackOverFlowService service ;

    @InjectMocks
    private StackOverFlowController controller;


    @Test
    public void getListOfProviders() throws URISyntaxException {
        List<StackOverFlowDto> allSites = service.getAllSites();

        when(service.getAllSites()).thenReturn(ImmutableList.of());
        List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
        verify(service).getAllSites();

    }
}

Я могу создать mock-объект следующим образом::

private StackOverFlowService service =  Mockito.mock(StackOverFlowService.class);

обновить 1

enter image description here

update 2

Wnen I have done this:

@RunWith(SpringRunner.class)
@WebMvcTest(StackOverFlowController.class)
public class StackOverFlowControllerTest {

    @Mock
    private StackOverFlowService service;

    @InjectMocks
     StackOverFlowController controller;


    @Test
    public void getListOfProviders() throws URISyntaxException {
        List<StackOverFlowDto> allSites = service.getAllSites();

        when(service.getAllSites()).thenReturn(ImmutableList.of());
        List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
        verify(service).getAllSites();

    }
}

Я получил ошибку:

PM org.junit.vintage.engine.descriptor.RunnerTestDescriptor warnAboutUnfilterableRunner ПРЕДУПРЕЖДЕНИЕ: Runner org.junit.internal.runners.ErrorReportingRunner (используется в классе com.spring.mon go .web.contollers.stackoverflow.StackOverFlowControllerTest) не поддерживает фильтрацию и поэтому будет выполняться полностью. org.junit.runners.model.InvalidTestClassError: Недействительный тестовый класс com.spring.mon go .web.contollers.stackoverflow.StackOverFlowControllerTest ':

  1. Нет запускаемых методов

enter image description here

where is the method get() from ?

update 3

This the test was performed:

@WebMvcTest(StackOverFlowController.class)
public class StackOverFlowControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private StackOverFlowService service;

    @MockBean
    private StackOverFlowController controller;

    @Test
    public void getListOfProviders() throws Exception {

        when(service.getAllSites()).thenReturn(ImmutableList.of());
        List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
        assertNotNull(listOfProviders);

   }
}

Но я не вижу в этом смысла. Я не получаю никаких данных:

 List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
  • Но здесь я должен получить набор элементов, но получаю 0

Обновление 4

Насколько я понимаю:

when(service.getAllSites()).thenReturn(ImmutableList.of());

Тестируем контроллер. Нижние слои нам не нужны. Нам нужно проверить, что вызывается метод

  • getListOfProviders () контроллера. Итак,
  • service.getAllSites () здесь мы указываем Mockito-object
@MockBean
    private StackOverFlowService service;

Этот метод должен возвращать какую-то коллекцию.

thenReturn(ImmutableList.of())

it должен возвращать пустую коллекцию.

Почему?

Я этого не понимаю.

List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();

Для чего это?

Обновить 5


    @Test
    public void getListOfProviders() throws Exception {

        when(service.getAllSites()).thenReturn(ImmutableList.of());
        List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
        assertNotNull(listOfProviders);

        verify(service).getAllSites();
    }
  • verify (сервис) .getAllSites (); Это должно подтвердить, что метод getAllSites () из интерфейса StackOverFlowService (из его реализации) вызовет ...

Но снова я получил ошибки:

Требуется, но не вызывается: com.spring.mon go .service.read.stackoverflow.StackOverFlowService # 0 bean.getAllSites (); -> at com.spring.mon go .web.contollers.stackoverflow.StackOverFlowControllerTest.getListOfProviders (StackOverFlowControllerTest. java: 38) На самом деле, с этим макетом не было никаких взаимодействий.

Требуется, но не вызывается : com.spring.mon go .service.read.stackoverflow.StackOverFlowService # 0 bean.getAllSites (); -> at com.spring.mon go .web.contollers.stackoverflow.StackOverFlowControllerTest.getListOfProviders (StackOverFlowControllerTest. java: 38) На самом деле, с этим макетом не было никаких взаимодействий.

Почему ?

Обновление 6

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringMongoApplication.class})
@WebMvcTest(StackOverFlowController.class)
class StackOverFlowControllerTestUnit {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private StackOverFlowService service;

    @MockBean
    private StackOverFlowController controller;

    @Test
    void getListOfProviders() throws Exception {

        MockHttpServletRequestBuilder requestBuilder =
                MockMvcRequestBuilders
                        .get("/api/stackoverflow")
                        .accept(MediaType.APPLICATION_JSON);

        mockMvc.perform(requestBuilder)
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.id").exists())
                .andDo(print());

    }
}

Здесь создаются beans, но я не получаю json ...

 .andExpect(MockMvcResultMatchers.jsonPath("$.sites").exists())
                .andExpect(MockMvcResultMatchers.jsonPath("$.sites[*].id").isNotEmpty());

Update_7

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringMongoApplication.class})
@WebMvcTest(StackOverFlowController.class)
public class StackOverFlowControllerTestFromForum {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private StackOverFlowService service;

    @InjectMocks
    private StackOverFlowController controller;

   @Test
   public void getListOfProviders() throws Exception {

        MockHttpServletRequestBuilder requestBuilder =
                MockMvcRequestBuilders
                        .get("/api/stackoverflow")
                        .accept(MediaType.APPLICATION_JSON);

        mockMvc.perform(requestBuilder)
                .andDo(print())
                .andExpect(status().isOk());
    }

}
  • В этой версии кода все bean-компоненты инициализируются без ошибок. @ InjectMocks - Это тоже работает.

    Обычное интеграционное тестирование, предлагаемое Spring, просто создает объекты, как если бы приложение работало в производственной среде. Я до сих пор не понимаю, для чего нужны Mock-объекты.

Здесь любые идеи закончены. Я не понимаю, почему это не работает.

Может кто-нибудь объяснить идею работы аннотаций @Mock и @InjectMocks применительно к этому примеру? Есть у кого-нибудь идеи?

Ответы [ 2 ]

0 голосов
/ 03 августа 2020

Если вы хотите, чтобы тест контроллера был таким же, как и любой другой класс модульного теста, тогда используйте spring для запуска тестов с аннотацией @RunWith(SpringRunner.class). Поскольку вы пишете модульный тестовый пример для контроллера, используйте метод тестирования, как показано ниже Вам просто нужно смоделировать вызов службы и вызвать метод контроллера или, что более уместно, ударить его с помощью mock mvc:

@Test
public void getListOfProviders() throws URISyntaxException {
    when(service.getAllSites()).thenReturn(ImmutableList.of());
    List<StackOverFlowDto> listOfProviders = controller.getListOfProviders();
    assertNotNull(listOfProviders);
}

Но если вы хотите, чтобы все было правильно, тогда:

@WebMvcTest
public class StackOverFlowControllerTest {
    
    @Mock
    private StackOverFlowService service ;

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getListOfProviders() throws URISyntaxException {
        when(service.getAllSites()).thenReturn(ImmutableList.of());
    this.mockMvc.perform(get("api/stackoverflow")).andDo(print()).andExpect(status().isOk());

    }
}

Если у вас возникли проблемы с @WebMvcTest, это означает, что у springboot возникают проблемы с настройкой тестовой среды из-за структуры проекта или аннотации в основном классе приложения, которые могут вызывать проблемы при настройке теста, поэтому в этом случае попробуйте настроить весь контекст приложения, как в интеграционном тесте (немного утомительный и ненужный), используя вместо этого аннотацию @SpringBootTest.

Официальный do c ссылка .

0 голосов
/ 03 августа 2020

Попробуйте использовать @RunWith(SpringRunner.class) вместо @RunWith(MockitoJUnitRunner.class), должно работать. SpringRunner поможет с внедрением зависимостей в макеты.

Изменить:

Попробуйте использовать следующий код:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringMongoApplication.class})
@WebMvcTest(StackOverFlowController.class)
public class StackOverFlowControllerTestUnit {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private StackOverFlowService service;

    @Test
    void getListOfProviders() throws Exception {

        MockHttpServletRequestBuilder requestBuilder =
                MockMvcRequestBuilders
                        .get("/api/stackoverflow")
                        .accept(MediaType.APPLICATION_JSON);

        mockMvc.perform(requestBuilder)
                .andDo(print())
                .andExpect(status().isOk());
                // .andExpect(MockMvcResultMatchers.jsonPath("$.id").exists())
                // .andDo(print());

    }
}

Попробуйте выполнить шаг за шагом. Если вышеперечисленное работает, возможно, вы сможете go для проверки пути json

...