简体   繁体   English

在 Spring Boot REST 控制器测试期间未触发语句时 Mockito

[英]Mockito when statement not triggering during Spring Boot REST Controller Test

I've written a typical three layer Spring Boot REST API and am building out the tests for it.我已经编写了一个典型的三层 Spring Boot REST API 并正在为其构建测试。 The API itself works fine but I am running into issues getting the controller tests to work. API 本身工作正常,但我遇到了让控制器测试工作的问题。 The body that's being returned is empty because the object the controller layer is getting back is null.返回的主体为空,因为控制器层返回的对象为空。 Here are the main dependencies in play.以下是主要的依赖项。

<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>

I've mocked out the service layer but the when statement in the test doesn't seem to be firing as I'd expect.我已经模拟了服务层,但测试中的 when 语句似乎并没有像我期望的那样触发。

Here's the test itself:这是测试本身:

@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());
    }
}

Here's the corresponding controller method:下面是对应的控制器方法:

@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);
     }

Here's the MockHTTPServletResponse.这是 MockHTTPServletResponse。 It has a status of 200 but the body is empty它的状态为 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 = []

For reference here's the service method that I'm trying to Mock作为参考,这里是我试图模拟的服务方法

    @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");
        }
    }

I've tried different versions of Springboot but that hasn't helped.我尝试过不同版本的 Springboot,但这没有帮助。 I had started off using 2.2.4 but I figured I would try the 2.1.X train since it has been around longer.我开始使用 2.2.4,但我想我会尝试使用 2.1.X 火车,因为它已经存在了更长的时间。 I can confirm the correct method in the controller is being called because of the log output I'm getting.由于我得到的日志输出,我可以确认正在调用控制器中的正确方法。

Try replacing the following line:尝试替换以下行:

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

with this (explicitity provide the class in any() ):有了这个(在any()明确提供类):

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

Ignore the following part, as @M.忽略以下部分,如@M。 Deinum pointed out that @MockBean does inject the mock object so this is irrelevant. Deinum 指出@MockBean确实注入了模拟对象,所以这无关紧要。


You did mock your service object but you didn't inject it into your controller.您确实模拟了服务对象,但没有将其注入控制器。

@InjectMocks
private VehicleController vehicleController = new VehicleController();

Initialize these mock objects using MockitoAnnotations.initMocks(this) and instead of autowiring MockMvc object try to pass your controller in it like this:使用MockitoAnnotations.initMocks(this)初始化这些模拟对象,而不是自动MockMvc对象,尝试像这样传递你的控制器:

@BeforeEach
void setup() {
    MockitoAnnotations.initMocks(this);

    this.mockMvc = MockMvcBuilders.standaloneSetup(vehicleController).build();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM