2017-07-17 20 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