我正在尝试使用JUnit,Mockito,Spring测试和Spring Security测试来测试Spring rest控制器类。以下是我正在进行测试的其他控制器类;
<ion-header>
<ion-navbar color="secondary">
<ion-title>
CEPs!
</ion-title>
</ion-navbar>
</ion-header>
<ion-content margin>
<ion-item ng-show="false">{{ item.cep + "\n" + item.logradouro + "\n" + item.complemento + "\n" + item.bairro + "\n" + item.localidade + "\n" +
item.uf}}
</ion-item>
<form margin-top (ngSubmit)="test()">
<ion-item>
<ion-input type="number" max="99999999" [(ngModel)]="form.cep" name="form"></ion-input>
</ion-item>
<button ion-button type="submit" center>Pesquisar CEP</button>
</form>
</ion-content>
以下是我的测试类;
@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);
}
}
}
我通过引用很多教程来完成上面的测试课程。问题是我无法清楚地理解一切。所以,我有以下疑惑。
我正在创建一个EmployeeService的模拟并使用@InjectMocks将其注入EmployeeRestController,那么为什么我会遇到以下失败;
@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();
}
}
MockMvcBuilders.webAppContextSetup(webApplicationContext).build();完全有效。
我知道MockMvcBuilders.standaloneSetup(employeeRestController)用于测试单个控制器类,弹出配置将不适用于此方法。我们怎样才能为这种方法提供弹簧配置,是否可能。
最后,这段代码如何:Mockito.reset(employeeService);作品。
答案 0 :(得分: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调用并且可以调用控制器。
它代表Dispatcher Servlet和所有必需的MVC组件, 允许我们在适当的Web环境中测试端点,但是 没有运行服务器的开销。
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()
的信息并控制它,调用重置 - 它是干净的所有信息。