Mockito, когда оператор не срабатывает во время теста REST Spring Boot Controller - PullRequest
0 голосов
/ 06 февраля 2020

Я написал типичный трехслойный API REST Spring Boot и строю тесты для него. Сам API работает нормально, но я сталкиваюсь с проблемами, заставляющими тесты контроллера работать. Возвращаемое тело пусто, потому что объект, возвращаемый уровнем контроллера, является нулевым. Вот основные зависимости в игре.

<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.Х, так как он дольше. Я могу подтвердить, что вызывается правильный метод в контроллере из-за вывода журнала, который я получаю.

1 Ответ

0 голосов
/ 06 февраля 2020

Попробуйте заменить следующую строку:

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

этим (в явном виде укажите класс в any()):

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

Игнорируйте следующую часть как @M. Дейнм указал, что @MockBean действительно вводит фиктивный объект, так что это не имеет значения.


Вы имитировали свой сервисный объект, но не вводили его в свой контроллер.

@InjectMocks
private VehicleController vehicleController = new VehicleController();

Инициализируйте эти фиктивные объекты, используя MockitoAnnotations.initMocks(this), и вместо автоматического подключения MockMvc object попытайтесь передать в него свой контроллер следующим образом:

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

    this.mockMvc = MockMvcBuilders.standaloneSetup(vehicleController).build();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...