Search code examples
spring-bootjunitmockitospring-test

Mock a MDC data in spring boot test


I want to mock a data which is fetched from MDC in test class other wise when the code executed it return a null value. So i try below,

@RunWith(SpringRunner.class)
@SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.MOCK,classes = TestApp.class)

public class Test {

    private MockMvc restMvc;

    @Before
    public void setUp() {
        mock(MDC.class);
        this.restMvc = MockMvcBuilders.standaloneSetup(TestController).build();    
    }       
    
    @Test
    public void testMe() throws Exception {            
     when(MDC.get("correlation-id")).thenReturn("1234");    
     //Req param and header are intialized          
     restMvc.perform(get("/assignments").headers(headers).params(reqParams).principal(token).accept(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().is2xxSuccessful());    
    }

}

But i am getting error,

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.

Solution

  • To mock a static method you should use Mockito.mockStatic method like this:

    try (var mockStatic = Mockito.mockStatic(MDC.class)) {
        mockStatic.when(() -> MDC.get("correlation-id"))
                  .thenReturn("1234");
    
        // rest of the test...
    }
    

    You can read more about it in the Mockito documentation. Additionally, I've reproduced the problem and tested the solution - you can see a commit in a GitHub repository with all required code. Please note that usage of mockito-inline is required for this to work - see this part of the docs.


    In case of your test, it would probably better to go with the approach proposed by @knittl in the comment - instead of mocking the get method, a value can be set in the MDC using the put method: MDC.put("correlation-id", "1234"). I've included both approaches in the GitHub repo mentioned before - both tests pass.