2017-07-17 54 views
0

我試圖用JUnit,Mockito,Spring測試和Spring Security測試來測試spring rest控制器類。以下是我正在執行測試的休息控制器類;Mockito失敗:其實,這個模擬零交互

@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的模擬,並使用@InjectMocks其注入EmployeeRestController,那麼爲什麼我得到以下故障;

    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(web應用上下文).build();確切地工作。

  3. 我知道MockMvcBuilders.standaloneSetup(employeeRestController)用於測試單獨的控制器類,並且彈簧配置將不可用於此方法。我們如何爲這種方法提供彈簧配置,是否有可能?最後,這段代碼如何實現:Mockito.reset(employeeService);作品。

回答

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模擬web容器,在所有可能的地方使用mock,但支持http調用並給出了調用控制器的可能性。

它代表了調度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); - 重置你之前setupped所有行爲。模擬包含來自when(), verify()的信息並控制它,調用重置 - 它清除所有信息。

+0

嗨,謝謝你的回答。但我仍然收到相同的失敗信息。 – karthi

+0

對不起,我沒有使用彈簧引導。 – karthi

+0

感謝您的幫助,我可以通過提供**測試上下文**來實現它,如[鏈接]中所建議的那樣(https://stackoverflow.com/questions/37369768/should-mockito-be-used-with -mockmvcs-webappcontextsetup合彈簧-4) – karthi