NoSuchMethodError in powermock spring boot?

Anirudh Jadhav picture Anirudh Jadhav · May 27, 2018 · Viewed 9.9k times · Source

Trying to Mock private method "mapCustomerToRule" in the same class with PowerMockito Spy but not able to get it. While it gives NoSuchMethodError.

but it still makes the private method call which in turn makes another thirdPartCall. I'm getting into a problem when thirdPartyCall throws the exception. As far as I understand, if I'm mocking the "mapCustomerToRule", it shouldn't get into method implementation detail and return the mock response.

public Map<String, List<Rule>> fetchCutomerToRules() {
        List<ClaimRuleEntity> listOfDHLClaimsRule = dhlClaimRuleRepository.findAllByOrderByRulePriority();

        if (Objects.isNull(listOfDHLClaimsRule) || listOfDHLClaimsRule.isEmpty()) {
            return null;
        }
        log.info("claim rules fetched from database");

        List<ClaimRuleCustomerEntity> listOfDHLClaimRuleCustomerEntity = dhlClaimRuleCustomerRepository.findAllByEnabledFlagTrue();

    if (Objects.isNull(listOfDHLClaimRuleCustomerEntity) || listOfDHLClaimRuleCustomerEntity.isEmpty()) {
        return null;
    }
    log.info("claim customers fetched from database");

    return mapCustomerToRule(listOfDHLClaimsRule, listOfDHLClaimRuleCustomerEntity);
}

private Map<String, List<Rule>> mapCustomerToRule(List<ClaimRuleEntity> listOfDHLClaimsRule,
        List<ClaimRuleCustomerEntity> listOfDHLClaimRuleCustomerEntity) {
    log.info("mapping started for claim rules to customer");
    Map<String, List<Rule>> cutomerToRules = new HashMap<>();

    listOfDHLClaimRuleCustomerEntity.forEach(dhlClaimRuleCustomerEntity -> {

        String customer = dhlClaimRuleCustomerEntity.getCustomer();
        List<Rule> rules = cutomerToRules.get(customer);

        if (Objects.isNull(rules)) {
            rules = new ArrayList<>();
            cutomerToRules.put(customer, rules);
        }

        for (ClaimRuleEntity dhlClaimRule : listOfDHLClaimsRule) {
            if (dhlClaimRule.getRuleId() == dhlClaimRuleCustomerEntity.getRuleId()) {
                Rule rule = new Rule();
                rule.setRuleId(dhlClaimRule.getRuleId());
                rule.setRuleValue(dhlClaimRuleCustomerEntity.getRuleValue());
                rule.setRulePriority(dhlClaimRule.getRulePriority());
                rule.setEnabled(dhlClaimRuleCustomerEntity.getEnabledFlag());
                rule.setRuleDescription(dhlClaimRule.getRuleDescription());
                rules.add(rule);
                break;
            }
        }
    });
    log.info("mapping completed for claim rules to customer");
    return cutomerToRules;

}

Here is the juint I wrote for classs

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(FetchUpdateClaimService.class)
@ContextConfiguration(classes = ProcessClaimTestConfiguration.class)
public class FetchUpdateClaimServiceTest {

    @Autowired
    FetchUpdateClaimService fetchUpdateClaimService;

    @Autowired
    ClaimRuleRepository dhlClaimRuleRepository;

    @Autowired
    ClaimRuleCustomerRepository dhlClaimRuleCustomerRepository;

    @Autowired
    ClaimRepository dhlClaimRepository;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void fetchCutomerToRules_should_pass_Test() throws Exception {
        FetchUpdateClaimService fetchUpdateClaimService = PowerMockito.spy(this.fetchUpdateClaimService);
        List<ClaimRuleEntity> listOfDHLClaimsRule = new ArrayList<>();
        ClaimRuleEntity claimRuleEntity = new ClaimRuleEntity();
        listOfDHLClaimsRule.add(claimRuleEntity);

        List<ClaimRuleCustomerEntity> listOfDHLClaimRuleCustomerEntity = new ArrayList<>();
        ClaimRuleCustomerEntity claimRuleCustomerEntity = new ClaimRuleCustomerEntity();
        listOfDHLClaimRuleCustomerEntity.add(claimRuleCustomerEntity);

        Map<String, List<Rule>> map = new HashMap<>();
        Mockito.when(dhlClaimRuleRepository.findAllByOrderByRulePriority()).thenReturn(listOfDHLClaimsRule);
        Mockito.when(dhlClaimRuleCustomerRepository.findAllByEnabledFlagTrue()).thenReturn(listOfDHLClaimRuleCustomerEntity);

        PowerMockito.doReturn(map).when(fetchUpdateClaimService,"mapCustomerToRule",Mockito.eq(List.class),Mockito.eq(List.class));

        this.fetchUpdateClaimService.fetchCutomerToRules();

    }

}

Error Stack:-

java.lang.NoSuchMethodError: org.mockito.internal.handler.MockHandlerFactory.createMockHandler(Lorg/mockito/mock/MockCreationSettings;)Lorg/mockito/internal/InternalMockHandler;
    at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMethodInvocationControl(DefaultMockCreator.java:114)
    at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:69)
    at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
    at org.powermock.api.mockito.PowerMockito.spy(PowerMockito.java:207)
    at com.morrison.process.claim.service.FetchUpdateClaimServiceTest.fetchCutomerToRules_should_pass_Test(FetchUpdateClaimServiceTest.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:149)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:141)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:132)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:141)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:121)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

My Pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-aws</artifactId>
            <version>${apache.camel.aws.version}</version>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>


        <dependency>
            <groupId>com.vladmihalcea</groupId>
            <artifactId>hibernate-types-52</artifactId>
            <version>2.2.0</version>
        </dependency>


        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>


        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>1.7.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>1.7.4</version>
            <scope>test</scope>
        </dependency>



    </dependencies>

Answer

Kohei TAMURA picture Kohei TAMURA · May 28, 2018

Try upgrading as follows:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.0-beta.5</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.0-beta.5</version>
    <scope>test</scope>
</dependency>

See also: