How can I mock a constructor with a parameter in Mockito?

How can I mock a constructor with a parameter in Mockito?

I have a class structured as follows:

public class A {
    public A(String test) {
        // Constructor logic
    }

    public String check() {
        // Method logic
    }
}

I want to mock the logic inside the constructor A(String test) and the check() method. My goal is to make any call like new A(any string).check() return a dummy string “test”.

I tried the following:

A a = mock(A.class); 
when(a.check()).thenReturn("test");

String test = a.check(); // This works, 'test' is returned as "test".

whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(a);
// I also tried:
// whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(a);

new A("random string").check();  // This doesn't work

However, this approach doesn’t seem to work. The call to new A(any string).check() is still executing the original constructor logic instead of returning the mocked object of A.

How can I properly create mockito mock constructor with a parameter?

To mock the constructor of class A and have it return a mocked instance, you need to use PowerMockito. PowerMockito allows you to mock constructors and static methods, which are not possible with standard Mockito.

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.whenNew;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class MockConstructorTest {

    @Test
    public void testMockConstructor() throws Exception {
        A mockA = mock(A.class);
        when(mockA.check()).thenReturn("test");

        whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(mockA);

        A a = new A("random string");
        String result = a.check();

        assertEquals("test", result);
    }
}

@PrepareForTest(A.class): This tells PowerMockito to prepare the class A for testing, allowing the constructor to be mocked.

whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(mockA): Mocks the constructor of A to return the mockA object whenever it’s instantiated with any string.

In some cases, you might want to partially mock the behavior of a class. You can use Mockito.spy to create a spy object that calls the real methods unless explicitly stubbed.

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import org.junit.Test;

public class MockConstructorTest {

    @Test
    public void testMockConstructorWithSpy() {
        A a = spy(new A("random string"));
        when(a.check()).thenReturn("test");

        String result = a.check();

        assertEquals("test", result);
    }
}
  • spy(new A(“random string”)): Creates a spy of the actual A object. The constructor is called, but you can still mock specific methods like check().

  • when(a.check()).thenReturn(“test”): Stubs the check() method to return “test”.

If mocking the constructor feels cumbersome or problematic, consider refactoring your code to be more test-friendly. For instance, you can use Dependency Injection to inject dependencies or parameters into the class instead of relying on complex constructor logic.

public class A {
    private final String value;

    public A(String value) {
        this.value = value;
    }

    public String check() {
        return "checked " + value;
    }
}

Then, in your tests, you can easily mock the behavior of the check() method:

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Test;

public class MockConstructorTest {

    @Test
    public void testMockWithRefactor() {
        A mockA = mock(A.class);
        when(mockA.check()).thenReturn("test");

        String result = mockA.check();

        assertEquals("test", result);
    }
}

Refactor your class to accept dependencies or parameters through methods or constructor injection. This simplifies the testing process by reducing the need for complex mocking.