程序流是否更深入到 MockMvc 中被模拟的 bean?

Does The program flow go deeper into the bean being mocked in MockMvc?

根据我对模拟的理解,测试不应该深入到被模拟的 bean 中。例如,控制流不应该进入函数 apiService.getSomeData() 而应该只是 return 字符串“Hello there”。 但是,模拟是如何工作的,还是程序会继续深入,我是否应该能够在标准输出中看到 getSomeData() 的打印语句?

当我实际 运行 下面的代码时,它并没有深入。但它应该如何工作?

假设这是 Rest Controller 代码:

@RestController
@RequestMapping(value = "/testing")
public class ApiController {

    @Autowired
    ApiService service;

    @PostMapping(path = "/events/notifications",consumes = "application/json", produces = "application/json" )
    public ResponseEntity<String> checkMapping(@Valid @RequestBody String someData, @RequestHeader(value="X-User-Context") String xUserContext) throws Exception {
        String response  = service.getSomeData(someData);
        return ResponseEntity.status(HttpStatus.OK).body(response);
    }
}

假设这是控制器测试代码:

@WebMvcTest(ApiController.class)
public class ApiControllerTest {

    @Autowired
    MockMvc mockMvc;
    @Autowired
    ObjectMapper mapper;

    @MockBean
    ApiService apiService;

    @Test
    public void testingApi() throws Exception {

        Mockito.when(apiService.getSomeData("")).thenReturn("Hello there");

        MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/testing/events/notifications")
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .header("X-User-Context","something")
                .content("something");

        mockMvc.perform(mockRequest)
                .andExpect(status().isBadGateway());

    }
}

假设这是 Api 服务代码:

@Service
public class ApiServiceImpl implements ApiService{

    @Override
    public String getSomeData(String data) throws Exception {

        System.out.println("Going deeper in the program flow);

        callThisFunction();

        return "Some data";
    }

    public void callThisFunction(){
        System.out.println("Going two levels deeper");
    }
}

在您的测试中,您根本不是在与 ApiServiceImpl 对话,而是与 mockito 创建的实例对话,该实例也在实现 ApiService 接口。因此,您的 getSomeData() 实现根本没有执行。这就是嘲笑的意义所在。你创建一个你不想执行的东西的“模拟”实现(或者让像 mockito 这样的工具为你做)并注入它而不是“真实”的东西。