Mockito is not mocking a final class method

443 views Asked by At

I have this code in my service and I'm trying to mock this execute(), context() and build():

Attributes attributes = targetClient.getAttributes(
                    TargetDeliveryRequest.builder()
                            .execute(new ExecuteRequest().mboxes(Collections.singletonList(mboxRequest)))
                            .context(new Context().channel(ChannelType.WEB)).build());

This TargetDeliveryRequest third-party library, so I can't change anything there...

public class TargetDeliveryRequest {
    ....
    public static TargetDeliveryRequestBuilder builder() {
        return new TargetDeliveryRequestBuilder();
    }

}

I'm trying to mock this execute(), context() and build():

TargetDeliveryRequestBuilder targetDeliveryRequestBuilder = mock(TargetDeliveryRequestBuilder.class);

However, this TargetDeliveryRequestBuilder is a final class, because of this I'm getting this error in the test execution:

org.mockito.exceptions.base.MockitoException: Cannot mock/spy class com.adobe.target.edge.client.model.TargetDeliveryRequestBuilder Mockito cannot mock/spy because : - final class

public final class TargetDeliveryRequestBuilder {
    ...
    TargetDeliveryRequestBuilder() {
    }
    ...
    public TargetDeliveryRequestBuilder context(Context context) {
        this.request.context(context);
        return this;
    }

    public TargetDeliveryRequestBuilder execute(ExecuteRequest execute) {
        this.request.execute(execute);
        return this;
    }
    ...
    public TargetDeliveryRequest build() {
        this.setTargetValues();
        this.setVisitorValues();
        this.createVisitorId();
        this.setExperienceCloudValues();
        TargetDeliveryRequest targetDeliveryRequest = TargetDeliveryRequest.fromRequest(this.request);
        targetDeliveryRequest.setLocationHint(this.locationHint);
        targetDeliveryRequest.setSessionId(this.sessionId);
        targetDeliveryRequest.setVisitor(this.visitor);
        targetDeliveryRequest.setDecisioningMethod(this.decisioningMethod);
        return targetDeliveryRequest;
    }
    ...
}

The only way I discovered in the other questions here on Stackover was to add mockito-inline ('org.mockito:mockito-inline:3.12.4'), this makes my test work well, however, as my project is old, the moment I add mockito-inline, it breaks a lot of other tests. In other words, this is not an option for me.

Similiar issues: How to mock a final class with mockito Mockito cannot mock/spy because : - final class

Does someone know how to mock this code? Thank you.

Versions: Java: 8 mockito-core: 3.12.4 powermock-module-junit: 2.0.9 powermock-api-mockito2: 2.0.9

1

There are 1 answers

0
Gustavo Rey On

I figured out how to solve this issue using PowerMockito following the code below:

import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({TargetDeliveryRequestBuilder.class, TargetDeliveryRequest.class})
public class MyTest {

    private TargetDeliveryRequestBuilder targetDeliveryRequestBuilder;
    
    @Before
    public void setUp() {
       targetDeliveryRequestBuilder = PowerMockito.mock(TargetDeliveryRequestBuilder.class);
    }

    @Test
    public void test() {
        PowerMockito.mockStatic(TargetDeliveryRequest.class);
        PowerMockito.when(TargetDeliveryRequest.builder()).thenReturn(targetDeliveryRequestBuilder);
    }

}