Ошибка Mockito: на самом деле с этим макетом не было никаких взаимодействий.

Я пытаюсь протестировать класс контроллера Spring Rest, используя JUnit, Mockito, Spring test и Spring Security test. Ниже приведен мой класс контроллера отдыха, для которого я выполняю тест;

@RestController
public class EmployeeRestController {

    @Autowired
    private EmployeeService employeeService;

    @PreAuthorize("hasAnyRole('ROLE_EMPSUPEADM')")
    @RequestMapping(value = "/fetch-timezones", method = RequestMethod.GET)
    public ResponseEntity<List<ResponseModel>> fetchTimeZones() {
        List<ResponseModel> timezones = employeeService.fetchTimeZones();
        return new ResponseEntity<>(timezones, HttpStatus.OK);
    }

}

Ниже приведен мой тестовый класс;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
@WebAppConfiguration
public class EmployeeRestControllerUnitTest {

private MockMvc mockMvc;

@Autowired
private WebApplicationContext webApplicationContext;

@Mock
private EmployeeService employeeService;

@InjectMocks
private EmployeeRestController employeeRestController;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
    Mockito.reset(employeeService);
    mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .build();
}

@Test
@WithMockUser(roles = {"EMPSUPEADM"})
public void testFetchTimezones() {
    try {
        mockMvc.perform(get("/fetch-timezones"))
          .andExpect(status().isOk())               
          .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
          .andExpect(jsonPath("$", hasSize(4)));
        verify(emploeeService, times(1)).fetchTimeZones();
        verifyNoMoreInteractions(employeeService);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

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

  1. Я создаю макет EmployeeService и внедряю его в EmployeeRestController с помощью @InjectMocks, тогда почему я получаю следующую ошибку;

    Wanted but not invoked:
    careGroupService.fetchTimeZones();
    -> at com.example.api.test 
    .restcontroller.EmployeeRestControllerUnitTest 
    .testFetchTimezones(EmployeeRestControllerUnitTest.java:73)
    Actually, there were zero interactions with this mock.
    
  2. Как MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); точно работает.

  3. Я знаю, что MockMvcBuilders.standaloneSetup(employeeRestController) предназначен для тестирования отдельных классов контроллеров, и конфигурация Spring не будет доступна для этого метода. Как мы можем предоставить конфигурацию Spring для этого метода, возможно ли это.

  4. Наконец, как работает этот фрагмент кода: Mockito.reset(employeeService); работает.


person karthi    schedule 17.07.2017    source источник


Ответы (1)


1) вы проверяете

verify(emploeeService, times(1)).fetchTimeZones();

но вы не настроили для него фиктивное поведение (до вызова mockMvc.perform(get("/fetch-timezones"))).

List<ResponseModel> timezones = new ArrayList<>();
when(emploeeService.fetchTimeZones()).thenReturn(timezones );

2) создать MockMvc из контекста. mockmvc эмулирует веб-контейнер, использует mock везде, где это возможно, но поддерживает http-вызов и дает возможность вызывать контроллер.

Он поддерживает Dispatcher Servlet и все необходимые компоненты MVC, что позволяет нам тестировать конечную точку в надлежащей веб-среде, но без дополнительных затрат на запуск сервера.

3) при использовании:

@MockBean private EmployeeService employeeService;

вы отвергаете реальный сервис. удалите его из тестового класса, реальный сервис будет использоваться при тестировании. Вместо использования @Mock используйте @MockBean. @MockBean переопределяется контейнером, с @Mock вам нужно ввести это в контроллер путем отражения

или без весенней загрузки с отражением:

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
    Mockito.reset(employeeService);
    mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .build();
    EmployeeRestController employeeRestController=  
            webAppContext.getBean(EmployeeRestController.class);
    ReflectionTestUtils.setField(employeeRestController, 
                                 "employeeService",
                                 employeeService);
}

4) Mockito.reset(employeeService);- вы сбрасываете все настройки поведения, которые вы настроили ранее. Мок содержит информацию от when(), verify() и управляет ею, call reset — очищает всю информацию.

person xyz    schedule 17.07.2017
comment
Привет, спасибо за ваши ответы. Но я все еще получаю то же сообщение об ошибке. - person karthi; 18.07.2017
comment
Извините, я не использую Spring Boot. - person karthi; 18.07.2017
comment
Спасибо за вашу помощь, я смог добиться этого, предоставив тестовый контекст, как это предлагается в этом Ссылка - person karthi; 18.07.2017