Search code examples
javaunit-testingmockito

Best practice to mock/stub object created by constructor in a method


(Currently I have junit and Mockito, PowerMock or EasyMock is not an option) Considering a POJO class with parameterized constructor

public class Pojo{
    private String field1;
    private String field2;

    public Pojo(String field1, String field2){
        this.field1=field1, this.field2=field2;
    }
}

Now I have a class requires unit test and one of the method create Pojo object by the constructor

public class AnInjectMock{

    private ServiceClass serviceClass;
    //....
    public void runTransaction(Param1 param1, Param2 param2 ...){

        Pojo pojo = new Pojo(param1.getFiel1(), param2.getField2();
        
        serviceClass.createTransaction(pojo, /*other fields*/};
        .....
    }
}

I think this is not an uncommon implementation scenario. But as for unit test, I try to figure out a way to use Mockito only to stub the constructor object. I get it that after Mockito 3.5 there is support to mock constructor, however per the document and other online tutorial I couldn't find anything to stub the object with parameterized constructor. I am Ok with any() value for the constructor.


Solution

  • If I understood correctly you need to mock parameters inside the object. I think you can easily mock this parameters with when()

        @ExtendWith(MockitoExtension.class)
        class AnInjectMockTest {
        
            @InjectMocks
            private AnInjectMock anInjectMock;
        
            @Mock
            private ServiceClass serviceClass;
        
            @Mock
            private Param1 param1;
        
            @Mock
            private Param2 param2;
        
            @Test
            public void myTest() {
                when(param1.getField1()).thenReturn(any());
                when(param2.getField2()).thenReturn(any());
                anInjectMock.createTransaction(pojo, /*other fields*/};
            }
    
    }
    

    By the way, why do you need to mock it? Maybe it's better to create an object from pojo and then mock createTransaction()

    Pojo pojo = new Pojo("field1Value", "field2Value");
    when(serviceClass.createTransaction(pojo, /*other fields*/)).thenReturn(any());
    

    And the last point. You can mock constructors with WhiteBox like:

    Pojo pojo = new Pojo("field1Value", "field2Value");
    Whitebox.setInternalState(anInjectMock, "pojo", pojo);
    

    But then you need to add dependency for WhiteBox:

    <!-- https://mvnrepository.com/artifact/org.powermock/powermock-reflect -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-reflect</artifactId>
        <version>1.6.1</version>
        <scope>test</scope>
    </dependency>