当语句在 Spring 启动 REST 控制器测试期间未触发时,Mockito



我已经编写了一个典型的三层Spring Boot REST API,并正在为其构建测试。API 本身工作正常,但我在让控制器测试工作时遇到了问题。返回的主体为空,因为控制器层返回的对象为 null。以下是主要的依赖关系。

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>  
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

我已经模拟了服务层,但测试中的 when 语句似乎没有像我预期的那样触发。

这是测试本身:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
public class VehicleControllerTest {
@MockBean
VehicleServiceImpl vService;
@Mock
HttpServletRequest mockRequest;
@Mock
Principal mockPrincipal;
@Autowired
MockMvc mockMvc;
Vehicle vehicle1;
@BeforeEach
public void setUp() throws ItemNotFoundException {
vehicle1 = new Vehicle();
vehicle1.setVin("5YJ3E1EA5KF328931");
vehicle1.setColor("black");
vehicle1.setDisplayName("Black Car");
vehicle1.setId(1L);
}
@Test
@WithMockUser("USER")
public void findVehicleByIdSuccess() throws Exception {
//Given **I think the problem is here***
when(vService.findVehicleById(any(),any(),any())).thenReturn(vehicle1);
//When
this.mockMvc.perform(get("/vehicles/1")).andDo(print())
//Then
.andExpect(status().isOk());
}
}

下面是相应的控制器方法:

@Secured("ROLE_USER")
public class VehicleController {

@JsonView(VehicleView.summary.class)
@GetMapping("/vehicles/{id}")
public Vehicle findVehicleById(@PathVariable Long id, Principal principal,
HttpServletRequest request) throws ItemNotFoundException {
log.info("In controller " +LogFormat.urlLogFormat(request,principal.getName()));       
return vehicleService.findVehicleById(id,principal, request);
}

这是MockHTTPServletResponse。它的状态为 200,但正文为空

MockHttpServletResponse:
Status = 200
Error message = null
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body = 
Forwarded URL = null
Redirected URL = null
Cookies = []

作为参考,这是我尝试模拟的服务方法

@Override
public Vehicle findVehicleById(Long id, Principal principal, HttpServletRequest request) throws ItemNotFoundException {
Optional<Vehicle> vehicle = vehicleRepository.findByIdAndUserId(id,principal.getName());     
if (vehicle.isPresent()){
return vehicle.get();
} else {
throw new ItemNotFoundException(id,"vehicle");
}
}

我已经尝试了不同版本的Springboot,但这并没有帮助。我开始使用 2.2.4,但我想我会尝试 2.1.X 火车,因为它已经存在了更长的时间。由于我得到的日志输出,我可以确认正在调用控制器中的正确方法。

尝试替换以下行:

when(vService.findVehicleById(any(),any(),any())).thenReturn(vehicle1);

有了这个(显式提供类any()(:

when(vService.findVehicleById(any(Long.class),any(Principal.class),any(HttpServletRequest.class))).thenReturn(vehicle1);

忽略以下部分,正如 @M. Deinum 指出的那样,@MockBean确实注入了模拟对象,因此这无关紧要。


您确实模拟了服务对象,但没有将其注入控制器。

@InjectMocks
private VehicleController vehicleController = new VehicleController();

使用MockitoAnnotations.initMocks(this)初始化这些模拟对象,而不是自动连接MockMvc对象尝试像这样传递控制器:

@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(vehicleController).build();

最新更新