mockConstruction doesn’t catch new ObjectMapper(). How to mock it like whenNew?

Mockito.mockConstruction does not return the mocked object

While replacing PowerMock with JUnit 5 features, I tried using mockConstruction instead of whenNew. However, Mockito.mockConstruction does not seem to return the mocked object, the test never goes inside the try block.

Here’s my setup:

@BeforeEach
void setUp() {
    partUnlinkService = spy(new PartVideoUnlinkService(part1, part2, part3));
}

Test method:

@Test
void shouldThrowException() throws Exception {
    UrlLinkDto urlLinkDto = UrlPartLinkDto.builder()
        .callId("333")
        .videoId("5555544")
        .build();

    ArgumentCaptor<UrlPartLinkDto> argumentCaptor = ArgumentCaptor.forClass(UrlPartLinkDto.class);

    try (MockedConstruction<ObjectMapper> ignoredVariable = mockConstruction(ObjectMapper.class,
        (objectMapper, context) -> {
            partUnlinkService.unlink(urlLinkDto, false);
            verify(partLogCheckService, times(1)).checkForExistingVideo(urlLinkDto.getVideoId());
            verify(objectMapper, times(1)).writeValueAsString(argumentCaptor.capture());
            Throwable throwable = catchThrowable(() -> objectMapper.writeValueAsString(argumentCaptor.capture()));
            assertThat(throwable).isInstanceOf(JsonProcessingException.class);
        })) {
    }
}

The issue: mockConstruction(ObjectMapper.class) does not seem to mock new object creation or trigger the callback. How can I ensure the mocked instance is used correctly, similar to how PowerMock’s whenNew worked?

The reason mockConstruction(ObjectMapper.class) isn’t catching your new ObjectMapper() is simply timing.

Mockito only intercepts constructor calls inside the active mockConstruction scope.

In your test, the constructor is invoked after the mock is created, but not while Mockito’s interception window is active. That’s why the callback never fires.

Fix: Make sure the code that creates the ObjectMapper runs inside the try(MockedConstruction...) block:

try (MockedConstruction<ObjectMapper> mocked = mockConstruction(ObjectMapper.class)) {
    partUnlinkService.unlink(urlLinkDto, false);

    ObjectMapper om = mocked.constructed().get(0);
    verify(om).writeValueAsString(any());
}

Anything constructed inside this block gets mocked. Anything outside it won’t — Mockito does not retroactively mock.

Adding to Tim’s explanation, it’s important to realize mockConstruction() is not a 1-to-1 replacement for PowerMock’s whenNew().

PowerMock rewrote bytecode to intercept constructor calls globally. Mockito does not do that.

Mockito only mocks constructors within the lifetime of the try-with-resources block. So if your new ObjectMapper() runs:

  • inside a service constructor
  • in a @BeforeEach setup
  • anywhere before entering the try block

…it will never be mocked.

To make Mockito behave like PowerMock, ensure that the actual construction happens after the mock scope begins:

try (MockedConstruction<ObjectMapper> mocked = mockConstruction(ObjectMapper.class)) {
    partUnlinkService.unlink(urlLinkDto, false);
}

This guarantees new ObjectMapper() falls inside the interception window.

To extend what both @tim-khorev and @devan-skeem explained, here’s a complete working example that behaves the closest to PowerMock’s whenNew(ObjectMapper.class):

@Test void shouldMockObjectMapperConstruction() throws Exception { UrlLinkDto dto = new UrlLinkDto(“333”, “5555544”);

try (MockedConstruction<ObjectMapper> mocked = mockConstruction(
        ObjectMapper.class,
        (mock, context) -> when(mock.writeValueAsString(any())).thenReturn("mocked"))) {

    partUnlinkService.unlink(dto, false);

    ObjectMapper mapperMock = mocked.constructed().get(0);
    verify(mapperMock).writeValueAsString(any());
}

}

Why this works:

  • The constructor fires inside the try block → Mockito intercepts it.
  • You can configure the mock (writeValueAsString) directly in the (mock, context) callback.
  • All constructed mocks are available via mocked.constructed().
  • And importantly: Mockito cannot mock already created instances, unlike PowerMock.

This is the cleanest Mockito-native equivalent of whenNew().