'How to mock controller parameter method with Mockito?

I have the following controller method where criterias is an object build with query parameters :

@GetMapping
public List<Employee> findAll(CustomCriteria criterias) {
     // this method build a custom mongoDB query object
     final Query query = criterias.buildMongoDBQueryFromCriteria();
     return employeeService.find(query);
}

The test is written as follow :

@Test
void get_all_employees_with_criterias() {

    given(employeeService.find(any(Query.class)))
            .willReturn(List.of(new Employee(), new Employee));

    final var responseBody = mvc.perform(get("/employees?companyId=12,14")
                    .accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andReturn()
                    .getResponse().getContentAsString();
    assertThatJson(responseBody).isArray().size().isEqualTo(2);
}

I can't find how to mock criterias.buildMongoDBQueryFromCriteria(). Indeed, there are a lot of logic inside this method, and I don't want it to be called for real with @WebMvcTest.

I have already tried to use @Spy annotation in the controller test class but it doesn't seems to work :/

I'm pretty sure that it must be really basic, but I didn't find any equivalent needs over Google.

Thanks for your help

EDIT

Based on @nnhthuan response I updated my test as follow, but it still doesn't work:

@Test
void get_all_employees_with_criterias() {

    var customCriteriaMock = Mockito.mock(CustomCriteria.class);
    var mockedQuery = Mockito.mock(Query.class);
    
 
when(customCriteriaMock.buildMongoDBQueryFromCriteria()).thenReturn(mockedQuery);

    given(employeeService.find(mockedQuery))
            .willReturn(List.of(new Employee(), new Employee()));

    final var responseBody = mvc.perform(get("/employees?companyId=12,14")
                    .accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk())
                    .andReturn()
                    .getResponse().getContentAsString();
    assertThatJson(responseBody).isArray().size().isEqualTo(2);
}


Solution 1:[1]

If you're asking how to write unit test, and this is how, not what you're trying to write above.

@Test
public void testFindAll() {
    CustomCriteria mockCriteria = Mockito.mock(CustomCriteria.class);
    Query mockQuery = Mockito.mock(Query.class);
    List<Employee> expectation = new ArrayList<>();
    when(mockCriteria.buildMongoDBQueryFromCriteria()).thenReturn(mockQuery);
    when(employeeService.find(mockQuery)).thenReturn(expectaion)
    
    List<Employee> actual = controller.findAll(mockCriteria);

    assertThat(actual).sameInstance(expectation); // Or whatever framework you are using to assert.
}

If you're asking how to write integration test with your real service, so do not use mocking framework. :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 nnhthuan